首页 > 解决方案 > 模拟函数在课堂上被覆盖

问题描述

我有一个实现 DocRaptor 的 pdf 创建器的类

public class PdfCreator {
  public byte[] createPdf(string html){
      int tryCount = 3;
      while(tryCount > 0) {
          try {
            Configuration.Default.Username = "YOUR_API_KEY_HERE"; // this key works for test documents
            DocApi docraptor = new DocApi();

            Doc doc = new Doc(
                // create a new doc object
            );

            AsyncDoc response = docraptor.CreateAsyncDoc(doc);

            AsyncDocStatus status_response;

            Boolean done = false;

            while(!done) {
                // Mocked this but it's getting ovewritten with a different StatusId
                status_response = docraptor.GetAsyncDocStatus(response.StatusId);

                Console.WriteLine("doc status: " + status_response.Status);
                switch(status_response.Status) {
                case "completed":
                    done = true;
                    byte[] doc_response = docraptor.GetAsyncDoc(status_response.DownloadId);
                    File.WriteAllBytes("/tmp/docraptor-csharp.pdf", doc_response);
                    Console.WriteLine("Wrote PDF to /tmp/docraptor-csharp.pdf");
                    break;
                case "failed":
                    done = true;
                    Console.WriteLine("FAILED");
                    Console.WriteLine(status_response);
                    break;
                default:
                    Thread.Sleep(1000);
                    break;
                }
            }
        } catch (DocRaptor.Client.ApiException error) {
            if (--tryCount == 0) throw;
        }
      }
    }
  }
}

在我的测试中,我试图通过模拟GetAsyncDocStatus调用返回一个状态来强制它失败并在 catch 块中抛出异常failed

_docRaptorService.Setup(p => p.GetAsyncDocStatus(It.IsAny<string>())).Returns("failed");

var docRaptor = new PdfCreator();

string html = $"<html><body><h1>Hello World!</h1></body></html>";

byte[] doc = docRaptor.createPdf(html);

_docRaptorService.Verify(p => p.GetAsyncDocStatus(It.IsAny<string>()), Times.Once);

但是当我运行测试时,测试失败,说该方法没有被调用。如果我在调试模式下运行测试,GetAsyncDocStatus返回completed而不是failed,这让我认为该类没有使用该方法的模拟版本。我该如何解决这个问题?

标签: c#moq

解决方案


下面的实现对我来说很好。删除了代码的某些部分,因为这里的目的只是为了确保模拟按预期工作。用于method injectionDependency Injection任何类型的DI都可以使用,比如constructorproperty等等。

public class PdfCreator
{
    public byte[] CreatePdf(string html, IDocApi docraptor)
    {
        try
        {           

            Boolean done = false;

            while (!done)
            {
                // Mocked this but it's getting ovewritten with a different StatusId
                var status_response = docraptor.GetAsyncDocStatus("testInput");

                Console.WriteLine("doc status: " + status_response);
                switch (status_response)
                {
                    case "completed":
                        done = true;
                        byte[] doc_response = docraptor.GetAsyncDoc("DownloadId");
                        File.WriteAllBytes("/tmp/docraptor-csharp.pdf", doc_response);
                        Console.WriteLine("Wrote PDF to /tmp/docraptor-csharp.pdf");
                        break;
                    case "failed":
                        done = true;
                        Console.WriteLine("FAILED");
                        Console.WriteLine(status_response);
                        break;
                    default:
                        Thread.Sleep(1000);
                        break;
                }
            }
        }
        catch (Exception)
        {
            throw;
        }

        return new byte[1];
    }
}

public interface IDocApi
{
    string GetAsyncDocStatus(string docId);
    byte[] GetAsyncDoc(string downloadId);
}

public class DocApi : IDocApi
{
    public byte[] GetAsyncDoc(string downloadId)
    {
        throw new NotImplementedException();
    }

    public string GetAsyncDocStatus(string docId)
    {
        return "completed";
    }
}

在单元测试中模拟了 IDocApi 接口并通过方法注入它。

 [TestClass]
public class UnitTest1
{
    [TestMethod]
    public void CreatePdfMethodGetAsyncDocStatusShouldReturnFailed()
    {
        Mock<IDocApi> mockDocApi = new Mock<IDocApi>();

        mockDocApi.Setup(m => m.GetAsyncDocStatus(It.IsAny<string>())).Returns("failed");

        PdfCreator sut = new PdfCreator();

        sut.CreatePdf("dummyHtml", mockDocApi.Object);

        //not asserting 
    }
}

工作截图 在此处输入图像描述


推荐阅读