2012-05-08 14 views
8

tôi có 2 lớp:Làm thế nào phương pháp ghi còn sơ khai với NUnit trong C#

  • FirstDeep.cs
  • SecondDeep.cs

    tôi đã mã đơn giản ví dụ:

 

class FirstDeep 
    { 
     public FirstDeep() { } 

     public string AddA(string str) 
     { 
      SecondDeep sd = new SecondDeep(); 
      bool flag = sd.SomethingToDo(str); 

      if (flag == true) 
       str = string.Concat(str, "AAA"); 
      else 
       str = string.Concat(str, "BBB"); 

      return str; 
     } 
    } 
 

class SecondDeep 
    { 
     public bool SomethingToDo(string str) 
     { 
      bool flag = false; 
      if (str.Length < 10) 
      { 
       //todo something in DB, and after that flag should be TRUE 
      } 
      return flag; 
     } 
    } 

Sau đó, tôi muốn viết unit test cho phương pháp "Adda":

class Tests 
    { 
     [Test] 
     public void AddATest() 
     { 
      string expected = "ABCAAA"; 

      FirstDeep fd = new FirstDeep(); 
      string res = fd.AddA("ABC"); 

      Assert.AreEqual(expected, res); 
     } 
    } 

Và sau đó tôi gặp khó khăn, tôi không biết làm thế nào đúng ghi stub cho phương pháp SomethingToDo trong class Test của tôi. Tôi luôn luôn có sai. Tôi chỉ nên trả TRUE. Nhưng bằng cách nào?

+0

bạn vẫn có thể làm việc với mẫu của mình: giới thiệu 'bool expected = false; SecondDeep sd = new SecondDeep(); bool actualResult = sd.SomethingToDo ("ABC"); Assert.AreEqual (excpected, actualResult); '...!? nếu điều này không đáp ứng nhu cầu của bạn, bạn có thể xem xét việc xây dựng và cải thiện câu hỏi của mình! –

+0

Bạn đã sửa mã của mình chưa? Nếu nó xảy ra trong cơ sở dữ liệu chúng tôi không thể giúp bạn vì chúng tôi không có chi tiết về những gì đang xảy ra ở đó. – Jon

+0

Có, tôi đã sửa lỗi mã của mình và tôi đã viết: "// cần làm gì đó trong DB và sau cờ đó phải là TRUE" Tôi sử dụng lớp MembershipUser từ .NET và phương pháp này không thể kết nối với DB, đó là lý do tôi nên chỉ trả lại đúng trong trường hợp này. – Smit

Trả lời

9

Một cách hay để cho phép bạn viết khai là sử dụng tiêm phụ thuộc. FirstDeep tùy thuộc vào SecondDeep và trong thử nghiệm của bạn, bạn muốn thay thế SecondDeep bằng cuống.

Đầu tiên thay đổi mã hiện tại của bạn bằng cách chiết xuất một giao diện cho SecondDeep và sau đó tiêm đó vào FirstDeep trong constructor:

interface ISecondDeep { 

    Boolean SomethingToDo(String str); 

} 

class SecondDeep : ISecondDeep { ... } 

class FirstDeep { 

    readonly ISecondDeep secondDeep; 

    public FirstDeep(ISecondDeep secondDeep) { 
    this.secondDeep = secondDeep; 
    } 

    public String AddA(String str) { 
    var flag = this.secondDeep.SomethingToDo(str); 
    ... 
    } 

} 

Lưu ý rằng FirstDeep không còn tạo ra một trường hợp SecondDeep. Thay vào đó một cá thể được tiêm vào hàm tạo.

Trong thử nghiệm của bạn, bạn có thể tạo một stub cho ISecondDeep nơi SomethingToDo luôn trả về true:

class SecondDeepStub : ISecondDeep { 

    public Boolean SomethingToDo(String str) { 
    return true; 
    } 

} 

Trong thử nghiệm bạn sử dụng stub:

var firstDeep = new FirstDeep(new SecondDeepStub()); 

Trong mã sản xuất bạn sử dụng "thực "SecondDeep:

Sử dụng một container tiêm phụ thuộc và một khuôn khổ stubbing có thể làm cho rất nhiều điều này dễ dàng hơn để làm.

Nếu bạn không muốn viết lại mã của mình, bạn có thể sử dụng khung để chặn các cuộc gọi như Microsoft Moles. Trong phiên bản tiếp theo của Visual Studio, một công nghệ tương tự sẽ có sẵn trong Fakes Framework.

4

Để làm cho mã của bạn có thể kiểm tra, không khởi tạo các phụ thuộc bên trong lớp học của bạn. Sử dụng dependency injection (thông qua hàm tạo, thuộc tính hoặc tham số). Đồng thời sử dụng các lớp hoặc giao diện trừu tượng để cho phép chế nhạo phụ thuộc:

class FirstDeep 
{ 
    private ISecondDeep oa; 

    public FirstDeep(ISecondDeep oa) 
    { 
     this.oa = oa; 
    } 

    public string AddA(string str) 
    { 
     return String.Concat(str, oa.SomethingToDo(str) ? "AAA" : "BBB"); 
    } 
} 

Tùy thuộc vào phép trừu tượng cho phép bạn kiểm tra lớp học của mình một mình.

interface ISecondDeep 
{ 
    bool SomethingToDo(string str); 
} 

class SecondDeep : ISecondDeep 
{ 
    public bool SomethingToDo(string str) 
    { 
     bool flag = false; 
     if (str.Length < 10) 
     { 
      // without abstraction your test will require database 
     } 
     return flag; 
    } 
} 

Đây là mẫu thử (sử dụng Moq).Nó cho bạn thấy cách bạn có thể trả lại true từ cuộc gọi đến sự phụ thuộc giả tạo của bạn:

[TestFixture] 
class Tests 
{ 
    [Test] 
    public void AddAAATest() 
    { 
     // Arrange 
     Mock<ISecondDeep> secondDeep = new Mock<ISecondDeep>(); 
     secondDeep.Setup(x => x.SomethingToDo(It.IsAny<string>())).Returns(true); 
     // Act 
     FirstDeep fd = new FirstDeep(secondDeep.Object); 
     // Assert 
     Assert.That(fd.AddA("ABD"), Is.EqualTo("ABCAAA")); 
    } 
} 
Các vấn đề liên quan