Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 访问moq对象时如何返回null?_C#_Unit Testing_Moq - Fatal编程技术网

C# 访问moq对象时如何返回null?

C# 访问moq对象时如何返回null?,c#,unit-testing,moq,C#,Unit Testing,Moq,我正在使用Moq库进行单元测试。现在我想要的是,当我第一次访问我的对象时,它应该返回null,当我第二次访问它时,它应该返回其他内容 这是我的密码 var mock = new Mock<IMyClass>(); mock.Setup(?????); mock.Setup(?????); var actual = target.Method(mock.object); 如何设置模拟对象 我还需要知道如何模仿这句台词 bool result = myObj.SomeFunction

我正在使用Moq库进行单元测试。现在我想要的是,当我第一次访问我的对象时,它应该返回null,当我第二次访问它时,它应该返回其他内容

这是我的密码

var mock = new Mock<IMyClass>();
mock.Setup(?????);
mock.Setup(?????);

var actual = target.Method(mock.object);
如何设置模拟对象

我还需要知道如何模仿这句台词

bool result = myObj.SomeFunctionReturningBool();

要模拟结果值,只需执行以下操作:

mock.Setup(foo => foo.SomeFunctionReturningBool()).Returns(true); // or false :)
对于另一个问题,只需在单元测试中通过null,而不是通过
mock.object
,您的单元测试也涵盖了这一点。因此,您基本上创建了两个单元测试,一个是:

var actual = target.Method(mock.object);
var actual = target.Method(null);
另一个有:

var actual = target.Method(mock.object);
var actual = target.Method(null);

听起来您正试图用一种测试方法运行两个测试-也许将测试分成两个更好

如果传递的方法为null,则还需要初始化新对象。为了测试这一点,我建议创建一个负责创建
MyClass
实例的工厂对象。新代码如下所示:

interface IMyClassFactory
{
    IMyClass CreateMyClass();
}

bool Method(IMyClass myObj, IMyClassFactory myClassFactory)
{
    if (myObj != null)
    {
        return true;
    }

    myObj = myClassFactory.CreateMyClass();
    return myObj.SomeFunctionReturningBool();
}
[Test]
public void Method_ShouldReturnTrueIfNotPassedNull()
{
    Assert.That(target.Method(new MyClass()), Is.True);
}

[Test]
public void Method_ShouldCreateObjectAndReturnResultOfSomeFunctionIfPassedNull()
{
    // Arrange
    bool expectedResult = false;

    var mockMyClass = new Mock<IMyClass>();
    mockMyClass.Setup(x => x.SomeFunctionReturningBool()).Returns(expectedResult);

    var mockMyFactory = new Mock<IMyClassFactory>();
    mockMyFactory.Setup(x => x.CreateMyClass()).Returns(mockMyClass.Object);

    // Act
    var result = target.Method(null, mockMyFactory.Object);

    // Assert
    mockMyClass.Verify(x => x.SomeFunctionReturningBool(), Times.Once());
    mockMyFactory.Verify(x => x.CreateMyClass(), Times.Once());
    Assert.That(result, Is.EqualTo(expectedResult));
}
然后,测试将如下所示:

interface IMyClassFactory
{
    IMyClass CreateMyClass();
}

bool Method(IMyClass myObj, IMyClassFactory myClassFactory)
{
    if (myObj != null)
    {
        return true;
    }

    myObj = myClassFactory.CreateMyClass();
    return myObj.SomeFunctionReturningBool();
}
[Test]
public void Method_ShouldReturnTrueIfNotPassedNull()
{
    Assert.That(target.Method(new MyClass()), Is.True);
}

[Test]
public void Method_ShouldCreateObjectAndReturnResultOfSomeFunctionIfPassedNull()
{
    // Arrange
    bool expectedResult = false;

    var mockMyClass = new Mock<IMyClass>();
    mockMyClass.Setup(x => x.SomeFunctionReturningBool()).Returns(expectedResult);

    var mockMyFactory = new Mock<IMyClassFactory>();
    mockMyFactory.Setup(x => x.CreateMyClass()).Returns(mockMyClass.Object);

    // Act
    var result = target.Method(null, mockMyFactory.Object);

    // Assert
    mockMyClass.Verify(x => x.SomeFunctionReturningBool(), Times.Once());
    mockMyFactory.Verify(x => x.CreateMyClass(), Times.Once());
    Assert.That(result, Is.EqualTo(expectedResult));
}
[测试]
public void方法\u应返回TrueIfNotPassedNull()
{
Assert.That(target.Method(new MyClass())为.True);
}
[测试]
public void方法\u应该CreateObjectandReturnResultToSomeFunctionIfPassedNull()
{
//安排
bool expectedResult=假;
var mockMyClass=new Mock();
mockMyClass.Setup(x=>x.SomeFunctionReturningBool()).Returns(expectedResult);
var mockMyFactory=new Mock();
mockMyFactory.Setup(x=>x.CreateMyClass()).Returns(mockMyClass.Object);
//表演
var result=target.Method(null,mockMyFactory.Object);
//断言
验证(x=>x.SomeFunctionReturningBool(),Times.Once());
验证(x=>x.CreateMyClass(),Times.Once());
Assert.That(result,Is.EqualTo(expectedResult));
}
这里使用传递一个对象,该对象可以创建
IMyClass
类型的对象,然后模拟工厂本身


如果不想更改方法的签名,则在类的构造函数中创建工厂,并通过类的公共属性使其可访问。然后,模拟工厂可以在测试中覆盖它。这被称为。

您可以使用带有参数的TestFixture。此测试将运行两次,并使用不同的类型值

using NUnit.Framework;

namespace Project.Tests
{
    [TestFixture(1)] 
    [TestFixture(2)]
    public class MyTest
    {
        private int _intType;

         public MyTest(int type)
         {
             _intType = type;
         }

        [SetUp]
        public void Setup()
        {
            if (_intType==1)
            {
                //Mock Return false
            }
            else
            {
                //Mock Return Value
            }
        }
    }
}

目前,SUT与
MyClass
实现紧密耦合。不能在SUT中模拟使用
new
关键字实例化的对象。因此,您不能单独测试SUT,并且您的测试不再是单元测试。当MyClass.SomeFunctionReturningBool的实现发生变化时(它将返回
true
而不是
false
),SUT测试将失败。这不应该发生。因此,将创建委托给某个依赖项(工厂),并将该依赖项注入SUT:

[Test]
public void ShouldReturnTrueWhenMyClassIsNotNull()
{
    Mock<IMyClassFactory> factory = new Mock<IMyClassFactory>();
    Mock<IMyClass> myClass = new Mock<IMyClass>();
    var foo = new Foo(factory.Object);
    Assert.True(foo.Method(myClass.Object));
}

[Test]
public void ShouldCreateNewMyClassAndReturnSomeFunctionValue()
{
    bool expected = true;
    Mock<IMyClass> myClass = new Mock<IMyClass>();
    myClass.Setup(mc => mc.SomeFunctionReturningBool()).Returns(expected);
    Mock<IMyClassFactory> factory = new Mock<IMyClassFactory>();
    factory.Setup(f => f.CreateMyClass()).Returns(myClass.Object);

    var foo = new Foo(factory.Object);

    Assert.That(foo.Method(null), Is.EqualTo(expected));
    factory.VerifyAll();
    myClass.VerifyAll();
}

Moq-returnnull-这个工作示例简单地说明了如何使用Moq返回null。虽然下面的注释行是必需的代码行,但下面提供了一个完整的工作示例

// _mockShopService.Setup(x => x.GetProduct(It.IsAny<string>())).Returns(() => null);

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

public class Product
{
    public string Id { get; set; }
    public string Name { get; set; }
}

public interface IShopService
{
    Product GetProduct(string productId);
}

public class ShopService : IShopService
{
    public Product GetProduct(string productId)
    {
        if (string.IsNullOrWhiteSpace(productId))
        {
            return new Product();
        }

        return new Product { Id = "8160807887984", Name = "How to return null in Moq" };
    }
}

public class Shop
{
    private static IShopService _shopService;

    public Shop(IShopService shopService)
    {
        _shopService = shopService;
    }

    public Product GetProduct(string productId)
    {
        Product product = _shopService.GetProduct(productId);

        return product;
    }
}

[TestClass]
public class ShopTests
{
    Mock<IShopService> _mockShopService;

    [TestInitialize]
    public void Setup()
    {
        _mockShopService = new Mock<IShopService>();
    }

    [TestMethod]
    public void ShopService_GetProduct_Returns_null()
    {
        //Arrange
        Shop shop = new Shop(_mockShopService.Object);

        //This is how we return null --- all other code above is to bring this line of code home
        _mockShopService.Setup(x => x.GetProduct(It.IsAny<string>())).Returns(() => null);

        //Act
        var actual = shop.GetProduct(It.IsAny<string>());

        //Assert

        Assert.IsNull(actual);
    }
}
/\u mockShopService.Setup(x=>x.GetProduct(It.IsAny())。返回(()=>null);
使用Microsoft.VisualStudio.TestTools.UnitTesting;
使用最小起订量;
公共类产品
{
公共字符串Id{get;set;}
公共字符串名称{get;set;}
}
公共接口IShopService
{
Product GetProduct(字符串productId);
}
公共类商店服务:IShopService
{
公共产品GetProduct(字符串productId)
{
if(string.IsNullOrWhiteSpace(productId))
{
退回新产品();
}
返回新产品{Id=“8160807887984”,Name=“如何在Moq中返回空值”};
}
}
公营商店
{
私人静态IShopService(零售服务);;
公共商店(IShopService shopService)
{
_shopService=shopService;
}
公共产品GetProduct(字符串productId)
{
Product Product=\u shopService.GetProduct(productId);
退货产品;
}
}
[测试类]
公共类商店测试
{
模拟商店服务;
[测试初始化]
公共作废设置()
{
_mockShopService=newmock();
}
[测试方法]
public void ShopService_GetProduct_Returns_null()
{
//安排
Shop-Shop=新店铺(_mockShopService.Object);
//这就是我们返回null的方式——上面所有其他代码都是将这行代码带回家
_mockShopService.Setup(x=>x.GetProduct(It.IsAny())。返回(()=>null);
//表演
var actual=shop.GetProduct(It.IsAny());
//断言
Assert.IsNull(实际值);
}
}

这与模拟无关,只需调用类中传递null的方法即可实现单元测试,我不太明白。创建mock的想法是不要将null作为IMayClass。如果需要null,那么只需调用
target.Method(null)
。第二个问题:你就是不能。您创建MyClass的实例,然后对其调用方法,这样它就不能被模拟。method else条件只有在myObj为null时才会运行,否则我必须调用SomeFunctionReturningBool,如果send null,则我不能模拟此函数,我已删除新的MyClass()行,我无法使用您的解决方案,因为只有当对象为null时,函数才会转到else,每次我向它传递模拟对象时,只有当条件将运行时,Method()的else条件才会在传递null时运行,但如果我向它传递null,则Obj.SomeFunctionReturningBool无法模拟,