繁体   English   中英

如何为返回 void 的方法编写 XUnit 测试用例

[英]How to write a XUnit test case for a method that does return void

如何为返回void的方法编写XUnit测试用例?

方法:

    public static void Print(string x)
    {
        Console.WriteLine(x);
    }

XUnit 测试用例 - (未完成)

    [Fact]
    public void ActionDelegatePrintTest()
    {
        Action<string> a= MaClass.Print;
         
        // How do I complete this test case ?

    }

我不能简单地使用Assert.Equal()因为它不返回任何东西。 那么我应该如何编写Assert语句呢?

您只能测试副作用,而您正在测试的 function 不允许您模拟任何东西,因此您无法测试任何东西。

如果您真的想测试某些内容已写入控制台,那么您需要抽象该功能,然后对其进行测试。

interface IConsoleWriter
{
   void WriteLine(string text);
}

IConsoleWriter _consoleWriter;
public void Print(string x)
    {
        _consoleWriter.WriteLine(x);
    }

[Fact]
public void ActionDelegatePrintTest()
{
    var sut = Mock.Of<IConsoleWriter>();
    sut.Print("Hello");
    sut.Verify(x=>x.Print("Hello"), Times.Once);  //<-- or whatever you need to test
}

您可以测试您想要的方法是否被调用,并且您可以测试 void function 中的任何其他方法是否被调用,它们采用不同的方法。

假设您正在使用或愿意使用 Moq,您可以按照我的示例进行操作

using Moq;
using Xunit;

namespace Tests;

public interface IMyLogger
{
    void Log();

    void Error();

    void Fatal();
}

public interface IMyClass
{
    void DoStuff();

    void DoSomethingElse();

    void CalledFromSomewhereInMyClass();
}

public class MyClass : IMyClass
{
    private readonly IMyLogger _logger;
    public MyClass(IMyLogger logger)
    {
        this._logger = logger;
    }

    public void DoStuff()
    {
        this._logger.Log();
    }

    public void DoSomethingElse()
    {
        this._logger.Error();
        this.CalledFromSomewhereInMyClass();
    }

    public void CalledFromSomewhereInMyClass()
    {
        this._logger.Error();
        this._logger.Fatal();
    }
}

public class MyClassTests
{
    private readonly Mock<IMyLogger> _loggerMock;
    public MyClassTests()
    {
        this._loggerMock = new Mock<IMyLogger>();
    }

    // Testing just that the method is called
    [Fact]
    public void TestDoStuffIsCalled()
    {
        var myClassMock = new Mock<IMyClass>();
        var myClassInstantiation = myClassMock.Object;

        myClassInstantiation.DoStuff();
        myClassMock.Verify(f => f.DoStuff(), Times.Once);
    }

    // Let's ensure the Logger.Log method is called
    [Fact]
    public void TestLoggerInsideDoStuffIsCalled()
    {
        var myClass = new MyClass(this._loggerMock.Object);
        myClass.DoStuff();

        this._loggerMock.Verify(f => f.Log(), Times.Once);
    }

    // Let's test chained calls to IMyLogger
    [Fact]
    public void TestChainCalls()
    {
        var myClass = new MyClass(this._loggerMock.Object);

        myClass.DoSomethingElse();
        this._loggerMock.Verify(f => f.Log(), Times.Never);

        // Note that Error is called from DoSomethingElse() and CalledFromSomewhereInMyClass() so it should be called twice
        this._loggerMock.Verify(f => f.Error(), Times.Exactly(2));
        this._loggerMock.Verify(f => f.Fatal(), Times.Once);
    }
}

如果您想测试一个确切的参数是否正确传递给您可以模拟的某个依赖项,请查看其他答案。

但是,如果您只想断言该方法已正确执行而不会引发异常,并且您在 xUnit 中找不到像 NUnit 的Assert.DoesNotThrow之类的东西,那么您可以通过以下方式解决它:

var exception = Record.Exception(() => MaClass.Print("some valid input"));
Assert.Null(exception);

实际上,您可以断言以非常相似的方式引发一些异常的无效参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM