c# - 模拟函数在课堂上被覆盖
问题描述
我有一个实现 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
,这让我认为该类没有使用该方法的模拟版本。我该如何解决这个问题?
解决方案
下面的实现对我来说很好。删除了代码的某些部分,因为这里的目的只是为了确保模拟按预期工作。用于method injection
,Dependency Injection
任何类型的DI
都可以使用,比如constructor
,property
等等。
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
}
}
推荐阅读
- react-native - 在同一行对齐文本和图像 React Native
- node.js - 如何从 aws sqs fifo 队列中读取消息?
- html - 使用 HTML 和 Typescript 打印出键/值对
- r - 无法使用 Dplyr 和 distinct() 过滤不同的行:没有适用于“distinct_”的方法应用于“因子”类的对象
- javascript - 在子容器上使用 CSS 变换时如何在父容器上手动设置溢出大小?
- reactjs - 如何防止浏览器缓存 webpack 包?
- python - 有没有办法使用python在系统命令窗口中运行几行连续的行
- azure - 本地 Azure 功能集成测试
- qt - GNU C 编译器不适用于 OSX 的 QT Creator
- spring-boot - Spring Boot 应用程序未启动。没有错误,但正在停止服务 [Tomcat]