简体   繁体   English

Moq - 模拟工厂不会在每次迭代时生成新对象

[英]Moq - mocking factory not generating new object with each iteration

I'm trying to moq and test the following method:我正在尝试最小起订量并测试以下方法:

public List<SkuCountByRetailerVm> GetSkuCountsByRetailer()
{
    var viewModels = _factory.GetEmptyListOfSkuCountByRetailerVms();
    foreach (var retailer in _helper.GetAllRetailersInReading())
    {
        var vm = _factory.GetSkuCountsByRetailerVm();
        vm.Retailer = retailer;
        vm.SkuCount = _helper.GetSkuCountByRetailerInReading(retailer);
        viewModels.Add(vm);
    }
    return viewModels;
}

The SkuCountByRetailerVm class is very basic data transfer object, it has got Retailer and SkuCount properties. SkuCountByRetailerVm 类是非常基本的数据传输对象,它具有 Retailer 和 SkuCount 属性。

The class under test depends on IFactory and IHelper, both of which I'm mocking in the test class.被测类依赖于 IFactory 和 IHelper,我在测试类中模拟了这两个类。

It looks like the code for the class under test is fine.看起来被测类的代码很好。 The problem when mocking is that I get 3 same viewmodels added to the list (all like the one which I expect to be added as last one), instead of 3 different ones.嘲笑时的问题是我将 3 个相同的视图模型添加到列表中(所有这些都类似于我希望添加为最后一个的视图模型),而不是 3 个不同的视图模型。 I think the problem with my test is that the way I setup the moq of the factory mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()).Returns(new SkuCountByRetailerVm());我认为我的测试的问题在于我设置工厂的起mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()).Returns(new SkuCountByRetailerVm());的方式mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()).Returns(new SkuCountByRetailerVm()); the vm just points to the same object, so I would rather need to have it instantiate a new vm each time? vm 只是指向同一个对象,所以我宁愿每次都需要它实例化一个新的 vm? Not sure if this is correct conclusion and if so how to do it differently way with Moq.不确定这是否是正确的结论,如果是,如何使用 Moq 以不同的方式做到这一点。

I paste the test class below should this be needed.如果需要,我粘贴下面的测试类。


[TestInitialize]
public void Setup()
{
    Mock<IReadingHelper> mockHelper = new Mock<IReadingHelper>();
    Mock<IVmFactory> mockFactory = new Mock<IVmFactory>();
    mockFactory.Setup(m => m.GetEmptyListOfSkuCountByRetailerVms()).Returns(new List<SkuCountByRetailerVm>());

    mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()).Returns(new SkuCountByRetailerVm());

    mockHelper.Setup(m => m.GetAllRetailersInReading()).Returns(
                new List<string> { "Fake1", "Fake2", "Fake3" });
    mockHelper.Setup(m => m.GetSkuCountByRetailerInReading("Fake1")).Returns(5);
    mockHelper.Setup(m => m.GetSkuCountByRetailerInReading("Fake2")).Returns(10);
    mockHelper.Setup(m => m.GetSkuCountByRetailerInReading("Fake3")).Returns(15);

    SkuCountByRetailerVmBuilder builder = new SkuCountByRetailerVmBuilder(mockHelper.Object, mockFactory.Object);

    _vms = builder.GetSkuCountsByRetailer();
}

The Returns method has lots of overloads. Returns方法有很多重载。

Currently you are using the one with the signature Returns(TResult) where you can specify the value to return and Moq use the same value every time the mocked method is called (so you get the same instance of your SkuCountByRetailerVm .目前,您正在使用带有签名Returns(TResult)那个,您可以在其中指定要返回的值,并且每次调用SkuCountByRetailerVm方法时,Moq 都使用相同的值(因此您将获得SkuCountByRetailerVm的相同实例。

You need to use one of the overloads which takes a Func<TResult> as a parameter with this can you specify a function that will calculate the value to return from the method:您需要使用以Func<TResult>作为参数的重载之一,您可以指定一个函数来计算从方法返回的值:

mockFactory.Setup(m => m.GetSkuCountsByRetailerVm())
           .Returns(() => new SkuCountByRetailerVm());

With this setup you will get a different instance every time your mocked method is caled.使用此设置,每次调用模拟方法时,您都会获得不同的实例。

Also, you can implement the IClonable Interface and use a special copy of the object whenever you want.此外,您可以实现IClonable接口并IClonable使用该对象的特殊副本。

 mockFactory.Setup(m => m.GetSkuCountsByRetailerVm()) .Returns(() => (SkuCountByRetailerVm)yourIntance.Clone());

This is a good way to mock sequences for retry requests to networks or databases.这是模拟对网络或数据库的重试请求的序列的好方法。

c# xUnit Moq It.IsAny<object> 没有像预期的那样嘲笑<div id="text_translate"><p>以下是一段代码(简单的 HTTP post 调用),我试图在 Azure 函数中模拟:</p><pre> await httpClient.PostAsync("https://url.com", await File.ReadAllTextAsync(Path.Combine(Environment.GetEnvironmentVariable("APP_DIRECTORY"), "file.json"));</pre><p> 请注意,httpClient.PostAsync() 函数有两个参数:URL 作为字符串,body 作为对象。</p><p> 现在,在我的测试中,我像这样模拟这个 POST 调用:</p><pre> httpClientMock.Setup(s =&gt; s.PostAsync(It.IsAny&lt;string&gt;(), It.IsAny&lt;object&gt;())).ReturnsAsync(mockedHttpResponse);</pre><p> 我期待await File.ReadAllTextAsync(Path.Combine(Environment.GetEnvironmentVariable("APP_DIRECTORY"), "file.json")不会被调用,因为我将它设置为与任何对象一起工作。但是,我的测试用例失败了例外:</p><blockquote><p> 在 System.IO.Path.Combine(String path1, String path2) 处发现 System.ArgumentNullException 消息“Value cannot be null. (Parameter 'path1')”</p></blockquote><p> 当我通过在测试中设置环境变量来提供正确的路径(即使是虚拟路径也不起作用)时,它就起作用了。 但这似乎不是正确的方法,因为单元测试旨在在各种机器上运行,并且每台机器的基本路径都不同。</p></div></object> - c# xUnit Moq It.IsAny<object> not mocking as expected

暂无
暂无

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

相关问题 使用Moq模拟&#39;new()&#39;约束 - Mocking the 'new()' constraint with Moq 使用Moq模拟访问者对象 - Mocking a visitor object using Moq 模拟复杂对象-使用Moq进行测试 - Mocking complex object - testing with Moq Moq具有“新”成员的模拟接口 - Mocking interfaces that have 'new' members with Moq 使用Moq在ElasticSearch中模拟单个Bucket对象 - Mocking a Single Bucket object in ElasticSearch using Moq 最小起订量-模拟.Object.MyMethod模拟不起作用 - Moq - mock.Object.MyMethod mocking does not work Moq&EF6 - 模拟EF6移除方法不移除对象 - Moq & EF6 - Mocking EF6 Remove method not removing an object 模拟一个抛出异常(moq)的方法,但其他方式就像模拟对象一样? - Mocking a method to throw an exception (moq), but otherwise act like the mocked object? c# xUnit Moq It.IsAny<object> 没有像预期的那样嘲笑<div id="text_translate"><p>以下是一段代码(简单的 HTTP post 调用),我试图在 Azure 函数中模拟:</p><pre> await httpClient.PostAsync("https://url.com", await File.ReadAllTextAsync(Path.Combine(Environment.GetEnvironmentVariable("APP_DIRECTORY"), "file.json"));</pre><p> 请注意,httpClient.PostAsync() 函数有两个参数:URL 作为字符串,body 作为对象。</p><p> 现在,在我的测试中,我像这样模拟这个 POST 调用:</p><pre> httpClientMock.Setup(s =&gt; s.PostAsync(It.IsAny&lt;string&gt;(), It.IsAny&lt;object&gt;())).ReturnsAsync(mockedHttpResponse);</pre><p> 我期待await File.ReadAllTextAsync(Path.Combine(Environment.GetEnvironmentVariable("APP_DIRECTORY"), "file.json")不会被调用,因为我将它设置为与任何对象一起工作。但是,我的测试用例失败了例外:</p><blockquote><p> 在 System.IO.Path.Combine(String path1, String path2) 处发现 System.ArgumentNullException 消息“Value cannot be null. (Parameter 'path1')”</p></blockquote><p> 当我通过在测试中设置环境变量来提供正确的路径(即使是虚拟路径也不起作用)时,它就起作用了。 但这似乎不是正确的方法,因为单元测试旨在在各种机器上运行,并且每台机器的基本路径都不同。</p></div></object> - c# xUnit Moq It.IsAny<object> not mocking as expected 使用Moq Mock对象模拟DbContext而不声明接口 - Mocking DbContext with Moq Mock object without declaring interface
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM