Unti Test:模拟方法结果

时间:2017-05-22 10:44:27

标签: c# unit-testing mocking

    public void Pay()
    {
        // some insert db code 
        // ...

        // Call Bank api
        BankApi api = new BankApi();
        int result = api.pay();
        if(result == 1)
        {
            //...
        }
        else
        {
            //...
        }
    }

我不想在单元测试中调用api。如何在不修改内码的情况下模拟pay方法(例如行new BankApi()代码)?

2 个答案:

答案 0 :(得分:3)

可以在不更改任何遗留代码的情况下模拟BankApi类,只需要一个允许模拟具体类的单元测试框架。 例如,使用Typemock测试您的方法:

[TestMethod]
public void ExampleTest()
{
    //fakes the next BankApi instace 
    var handler = Isolate.Fake.NextInstance<BankApi>();

    //change the pay method behavior
    Isolate.WhenCalled(() => handler.pay()).WillReturn(1);

    new ClassUnderTest().Pay();
}

答案 1 :(得分:2)

首先,如上所述,您应该创建一个接口。

import os

start_dir = os.getcwd()

for t in [1, 2, 3]:
    this_dir_rel = "../data/train/Type_%d" % ( t )
    this_dir_abs = os.path.join(start_dir, this_dir_rel)
    os.chdir(this_dir_abs)

然后,你可以做的是像这样模拟这个界面(我在这里使用Moq“模拟你”,你需要添加NuGet包“Moq”作为你的应用程序的参考,你可以使用其他模拟当然是图书馆)

public interface IBankApi 
{
    int pay();
}

之后你会告诉这个电话应该返回什么(这将是真正的嘲笑)

apiMock = new Mock<IBankApi>();

然后,这个api“伪对象”可以通过使用apiMock.Object

来使用

现在,我刚给你的这些信息并没有直接解决你的问题。

如评论中所述,您需要更好地解耦代码。

例如,您需要某种“依赖注入”来允许这种解耦。

以下是一个如何完成的简单示例:

apiMock.Setup(x => x.pay()).Returns(1); // 

如何对该方法进行单元测试:

public class ClassThatUsesYourBankApi 
{
    private readonly IBankApi _api;

    // the constructor will be given a reference to the interface
    public ClassThatUsesYourBankApi (IBankApi api)
    {
        // here you could check for null parameter and throw exception as needed
        this._api = api;
    }

    // this method can now be tested with the mock interface 
    public void MethodThatUseTheApi() 
    {
        int result = this._api.pay();

        if (result == 1) 
        {
            // some things that happens   
        }
        else
        {
            // some other thing
        }
    }
}

这里要理解的关键是,你不能在想要测试的方法中实例化你需要的api

换句话说,通过编程到接口来完成将你的方法与你的api“解耦”,以及你没有的代码 using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; [TestClass] public class TestMyMethod { [TestMethod] public void MyMethod_WithBankApiReturns1_ShouldHaveThingsThatHappens() { // Arrange var apiMock = new Mock<IBankApi>(); apiMock.Setup(api => api.pay()) .Returns(1); var myObject = new ClassThatUsesYourBankApi(apiMock.Object); // Act int result = myObject.MethodThatUseTheApi(); // Assert // Here you test that the things that should have happened when the api returns 1 actually have happened. } } 直接在你想要进行单元测试的方法中。

我展示了一种方法,还有其他方法。