확장 방법을 모의하기 위해 Moq를 어떻게 사용합니까?
확장 메서드의 결과에 따라 달라지는 테스트를 작성하고 있지만 해당 확장 메서드의 향후 실패로 인해이 테스트가 중단되는 것을 원하지 않습니다. 그 결과를 조롱하는 것이 당연한 선택으로 보였지만 Moq는 정적 메서드 (확장 메서드에 대한 요구 사항) 를 재정의하는 방법을 제공하지 않는 것 같습니다 . Moq.Protected 및 Moq.Stub에도 유사한 아이디어가 있지만이 시나리오에 대해서는 아무것도 제공하지 않는 것 같습니다. 내가 뭔가를 놓치고 있습니까? 아니면 다른 방식으로 진행해야합니까?
다음은 일반적인 "재정의 할 수없는 멤버에 대한 잘못된 기대"로 실패하는 간단한 예입니다 . 이것은 확장 메서드를 모의해야하는 나쁜 예이지만 그래야합니다.
public class SomeType {
int Id { get; set; }
}
var ListMock = new Mock<List<SomeType>>();
ListMock.Expect(l => l.FirstOrDefault(st => st.Id == 5))
.Returns(new SomeType { Id = 5 });
대신 Isolator를 사용하도록 제안 할 수있는 TypeMock 중독자에 대해서는 TypeMock이 눈을 가리고 술에 취해 작업을 수행 할 수있는 것처럼 보이므로 노력에 감사하지만 예산이 곧 증가하지는 않습니다.
확장 메서드는 변장 된 정적 메서드 일뿐입니다. Moq 또는 Rhinomocks와 같은 모의 프레임 워크는 개체의 모의 인스턴스 만 만들 수 있습니다. 즉, 정적 메서드 모의는 불가능합니다.
확장 메서드 코드를 변경할 수 있다면 다음과 같이 코딩하여 테스트 할 수 있습니다.
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
public static class MyExtensions
{
public static IMyImplementation Implementation = new MyImplementation();
public static string MyMethod(this object obj)
{
return Implementation.MyMethod(obj);
}
}
public interface IMyImplementation
{
string MyMethod(object obj);
}
public class MyImplementation : IMyImplementation
{
public string MyMethod(object obj)
{
return "Hello World!";
}
}
따라서 확장 메서드는 구현 인터페이스를 둘러싼 래퍼 일뿐입니다.
(당신은 일종의 구문 설탕 인 확장 메소드없이 구현 클래스 만 사용할 수 있습니다.)
그리고 구현 인터페이스를 모의하고 확장 클래스에 대한 구현으로 설정할 수 있습니다.
public class MyClassUsingExtensions
{
public string ReturnStringForObject(object obj)
{
return obj.MyMethod();
}
}
[TestClass]
public class MyTests
{
[TestMethod]
public void MyTest()
{
// Given:
//-------
var mockMyImplementation = new Mock<IMyImplementation>();
MyExtensions.Implementation = mockMyImplementation.Object;
var myObject = new Object();
var myClassUsingExtensions = new MyClassUsingExtensions();
// When:
//-------
myClassUsingExtensions.ReturnStringForObject(myObject);
//Then:
//-------
// This would fail because you cannot test for the extension method
//mockMyImplementation.Verify(m => m.MyMethod());
// This is success because you test for the mocked implementation interface
mockMyImplementation.Verify(m => m.MyMethod(myObject));
}
}
I know this question hasn't been active for about a year but Microsoft released a framework to handle exactly this called Moles.
Here are a few tutorials as well:
I created a wrapper class for the extension methods that I needed to mock.
public static class MyExtensions
{
public static string MyExtension<T>(this T obj)
{
return "Hello World!";
}
}
public interface IExtensionMethodsWrapper
{
string MyExtension<T>(T myObj);
}
public class ExtensionMethodsWrapper : IExtensionMethodsWrapper
{
public string MyExtension<T>(T myObj)
{
return myObj.MyExtension();
}
}
Then you can mock the wrapper methods in your tests and code with your IOC container.
For extension methods I normally use the following approach:
public static class MyExtensions
{
public static Func<int,int, int> _doSumm = (x, y) => x + y;
public static int Summ(this int x, int y)
{
return _doSumm(x, y);
}
}
It allows to inject _doSumm fairly easy.
참고URL : https://stackoverflow.com/questions/562129/how-do-i-use-moq-to-mock-an-extension-method
'Nice programing' 카테고리의 다른 글
Docker는 7000에서 8000까지의 모든 포트 또는 포트 범위를 노출합니다. (0) | 2020.10.12 |
---|---|
이 구조는 어떻게 sizeof == 0을 가질 수 있습니까? (0) | 2020.10.12 |
JSON 문자 인코딩-브라우저에서 UTF-8을 잘 지원합니까 아니면 숫자 이스케이프 시퀀스를 사용해야합니까? (0) | 2020.10.12 |
MySQL 대 SQL Server 대 Oracle (0) | 2020.10.12 |
일부 속성 값이있는 노드를 선택하는 XPath는 다른 노드의 속성 값과 동일합니다. (0) | 2020.10.12 |