Nhiều đối số phù hợp Moq It.Is <string> ()


77

Với Moq, việc có nhiều hơn một Đối số phù hợp có hợp lệ không?

It.Is<string>() 

Trong ví dụ này, tôi muốn mockMembershipService trả về một ProviderUserKey khác tùy thuộc vào Người dùng được cung cấp.

mockMembershipService.Setup(
    x => x.GetUser(
      It.Is<string>(
        s => s.Contains("Joe")))
   .ProviderUserKey)
.Returns("1234abcd");


mockMembershipService.Setup(
  x => x.GetUser(
    It.Is<string>(
      s => s.Contains("Tracy")))
  .ProviderUserKey)
.Returns("5678efgh");

SetUp mặc định là câu lệnh thứ hai thay vì đánh giá mỗi câu lệnh dựa trên giá trị của chính nó.

Câu trả lời:


54

Không khó hiểu phải không? Bạn đang cố gắng mô phỏng phương thức GetUser nhưng bạn đặt Giá trị trả về cho thuộc tính giá trị trả về của hàm đó. Bạn cũng muốn chỉ ra thuộc tính của loại trả về dựa trên phương thức được chế tạo.

Đây là một cách rõ ràng hơn:

mockMembershipService.Setup(x => x.GetUser(It.IsAny<string>())
                     .Returns<string>(GetMembershipUser);

Đây là một phương pháp để tạo mô hình thành viên:

private MembershipUser GetMembershipUser(string s)
{
    Mock<MembershipUser> user =new Mock<MembershipUser>();
    user.Setup(item => item.ProviderUserKey).Returns(GetProperty(s));
    return user.Object;
}

Sau đó, bạn viết một phương thức để thiết lập thuộc tính đó:

private string GetProperty(string s)
{
    if(s.Contains("Joe"))
        return "1234abcd";
    else if(s.Contains("Tracy"))
        return "5678efgh";
}

1
Sẽ cố gắng này trong thời gian ngắn, đã nhìn vào video này thethoughtfulcoder.com/blog/52/... khi bạn thêm vào câu trả lời của bạn mà làm điều gì đó tương tự
Nicholas Murray

các mã trên sẽ không biên dịch nó than phiền về Security.MembershipUser không chứa một tham chiếu cho lợi nhuận và cũng về tài khoản không chứa định nghĩa cho ProviderUserKey
Nicholas Murray

Bạn nên tham khảo phần lắp ráp Security.MembershipUser, tôi đoán vậy. Hoặc bạn có thể tạo phụ thuộc để tạo người dùng cho bạn trong Dịch vụ thành viên của bạn
Ufuk Hacıoğulları

hmmm - nó không phàn nàn về điều đó khi tôi đang cố gắng theo cách của tôi - (mà không hoạt động như desited tất nhiên)
Nicholas Murray

Tôi đoán bạn có thể viết một hàm khác để tạo một mô hình MemberhipUser nhưng nó đang bị thất bại nghiêm trọng. Tôi đã cập nhật mã.
Ufuk Hacıoğulları

35

Nếu bạn muốn giới hạn đầu vào chỉ "Joe" và "Tracy", bạn có thể chỉ định nhiều điều kiện trong It.Is<T>(). Cái gì đó như

mockMembershipService.Setup(x => x.GetUser(It.Is<String>(s => s.Contains("Joe") 
                                                         || s.Contains("Tracy")))
    .Returns<string>(/* Either Bartosz's or Ufuk's answer */);

Đó không phải là điều tôi muốn hạn chế, tôi chỉ muốn đánh giá đầu vào và trả về đầu ra mong muốn :-)
Nicholas Murray

Bất kể điều này có đúng chỗ hay không, nó đã giúp tôi giải quyết vấn đề, cảm ơn @ staffll0
Jacob McKay

15

Các lệnh gọi Thiết lập Succesive vô hiệu hóa các thiết lập trước đó.

Bạn có thể sử dụng đối số của mình trong lệnh gọi lại trả về:

mockMembershipService.Setup(x => x.GetUser(It.IsAny<string>()).ProviderUserKey).Returns<string>(s =>
{
    if(s.Contains("Joe"))
        return "1234abcd";
    else if(s.Contains("Tracy"))
        return "5678efgh";
});

Nếu điều quan trọng là bạn phải khẳng định đối số đã được thông qua, bạn cũng cần It.Is<string>(...)thay thế It.IsAny<string>(...).


Tôi sẽ thử cái này trong khoảng 2 giờ.
Nicholas Murray

À, tôi nghĩ đó là vì chúng tôi đang thiết lập một tài sản ở đây ( ProviderUserKey), trong khi lập luận mà chúng tôi đang cố gắng hành động đến từ GetUser(...). Không thể kiểm tra giải pháp thích hợp ngay bây giờ, nhưng nếu bạn làm theo lời khuyên Ufuk, nó phải là ok ...
Bartosz

Tôi sẽ thử vào cuối tuần - cảm ơn sự giúp đỡ của bạn! Không thẳng tiến như tôi nghĩ đầu tiên.
Nicholas Murray

@mattumotu: Đó không phải là những gì tôi trải nghiệm, Moq chỉ có một chính sách thực thi kỳ lạ. Các cuộc gọi Thiết lập được thêm vào sau đó được đánh giá trước (hoặc luôn luôn được đánh giá và thắng cuối cùng). Nó hoàn toàn ngược lại với những gì người ta mong đợi: Thường thì trận đấu đầu tiên được trả về và phần còn lại bị bỏ qua.
Christoph

7

Vui lòng kiểm tra tài liệu Giới thiệu về Moq> Đối số phù hợp :

// matching Func<int>, lazy evaluated
mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true); 


// matching ranges
mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns(true); 


// matching regex
mock.Setup(x => x.DoSomething(It.IsRegex("[a-d]+", RegexOptions.IgnoreCase))).Returns("foo");

3
Giờ đây, với kinh nghiệm nhiều hơn về Bài kiểm tra đơn vị, tôi không khuyên bạn nên sử dụng kiểu tiếp cận này. Chúng ta nên tránh đặt logic trong Unit Test. Một tùy chọn khác là tạo các bài kiểm tra đơn vị riêng biệt: một cho Joe và một cho Tracy
Jaider
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.