Moq Mock 单元测试:带有一个实例的 Moq Mock 设置,以及带有另一个实例的 SUT 业务代码,但两者具有相同的内容。为什么会失败?

问题描述 投票:0回答:1

以下是有关我们技术开发环境的信息:

• .NET 6

• C# 10

• Microsoft.NET.Test.Sdk”版本 15.5.0

• 起订量版本 4.18.2

• Xunit 版本 2.4.1

public class Vehicle  {
     public string VIN { get; set; }
     public string CarCompany { get; set; }
     public string Model  { get; set; }
}
public interface IBlahClient : IDisposable {
             
  Task<TResponse> SendQuery<TResponse>( string aVehicleJsonString, CancellationToken cancellationToken = default);

 }
public class BlahClient : IBlahClient {

       public Task<TResponse> SendQuery<TResponse>( string aVehicleJsonString,  
CancellationToken cancellationToken = default)
    {

         Return ……;
    } 
 }
 public class VehicleProcessor {

    public static string ConvertToJSON( Vehicle aVehicle ){
             …….blah blah blah blah code…..
            return aVehicleJsonString;

         }
public string SendVehicleInfoToDMV( IBlahClient client, Vehicle aVehicle ){
            string aVehicleJsonString = ConvertToJSON(aVehicle );
              
            string response = client. SendQuery<string>(  aVehicleJsonString, CancellationToken.None);

             return response;
 } 

}

 public class VehicleProcessorSUTClass {
       [Fact]
        public void Test()
        {
                  
                 Vehicle aVehicle = ..…BlahBlah Code for instantiating a Vehicle instance…..
                
                string aVehicleJsonString = VehicleProcessor.ConvertToJSON( aVehicle );

                    VehicleProcessor aVehicleProcessorSUT = new VehicleProcessor();
                
         Mock<IBlahClient> blahClientMock = new Mock<IBlahClient>();

                   blahClientMock.Setup(c => c.SendQuery<string>(aVehicleJsonString , CancellationToken.None))
                         .Returns(aVehicleJsonString);

                 string response = aVehicleProcessorSUT. SendVehicleInfoToDMV(blahClientMock.Object, aVehicle );
               //// Unfortunately response turns out to be null /////
              } }

我理解两次调用 ConvertToJSON 的复杂微妙的细微差别,这将导致 2 个具有相同内容的不同 json 字符串实例:

  1. 在 Moq 测试代码中,我调用 ConvertToJSON ,并将结果用于 blahClientMock 的 SendQuery 方法的 Moq 设置。

  2. 在实际 SUT 的业务代码本身中,我调用 ConvertToJSON

但是,即使有 2 个不同的 aVehicleJsonString 实例,它们仍然具有相同的内容。为什么SUT业务代码在单元测试时返回null?

c# unit-testing mocking moq
1个回答
0
投票

从您提供的代码中,有一些突出的事情可能导致问题:

  1. 方法名称不匹配:在

    IBlahClient
    接口中,您有一个名为
    SendQueryAsync
    的方法,但在
    VehicleProcessor
    类中,您正在调用名为
    SendQuery
    的方法。这将导致编译时错误。确保方法名称匹配。

  2. 异步/等待模式

    SendQueryAsync
    方法是异步的,但在
    await
    类中调用它时没有使用
    VehicleProcessor
    关键字。这意味着您实际上并没有获得该方法的结果,而是获得了一个
    Task
    对象。您应该等待该方法才能获得结果。

  3. 模拟设置:当您设置模拟时,您使用的是方法

    SendQuery<dynamic>
    ,但界面中的实际方法是
    SendQueryAsync<TResponse>
    。这意味着您的模拟设置可能与实际的方法调用不匹配,因此模拟不会返回预期值,您会得到
    null

我已经提供了相关部分的更新版本:

  1. 更新
    VehicleProcessor
    类以使用
    await
    :
public async Task<string> SendVehicleInfoToDMV(IBlahClient client, Vehicle aVehicle)
{
    string aVehicleJsonString = ConvertToJSON(aVehicle);
    string response = await client.SendQueryAsync<string>(aVehicleJsonString, CancellationToken.None);
    return response;
}
  1. 更新您的测试方法以匹配正确的方法并使用 async/await:
[Fact]
public async Task Test()
{
    Vehicle aVehicle = ...; // Your code for instantiating a Vehicle instance
    string aVehicleJsonString = VehicleProcessor.ConvertToJSON(aVehicle);
    VehicleProcessor aVehicleProcessorSUT = new VehicleProcessor();

    Mock<IBlahClient> blahClientMock = new Mock<IBlahClient>();
    blahClientMock.Setup(c => c.SendQueryAsync<string>(aVehicleJsonString, CancellationToken.None))
                  .ReturnsAsync(aVehicleJsonString);

    string response = await aVehicleProcessorSUT.SendVehicleInfoToDMV(blahClientMock.Object, aVehicle);
    Assert.Equal(aVehicleJsonString, response); // Add this assertion to check if the response matches the expected value
}
  1. 确保
    BlahClient
    类正确实现
    SendQueryAsync
    接口中的
    IBlahClient
    方法。

我为您的测试提供的这些更改应该按预期工作。如果您仍然遇到问题,请确保

ConvertToJSON
方法是确定性的,并为相同的输入生成相同的 JSON 字符串。

© www.soinside.com 2019 - 2024. All rights reserved.