【问题标题】:How to mock a generic method to return concrete type?如何模拟泛型方法以返回具体类型?
【发布时间】:2017-12-09 15:19:18
【问题描述】:

我正在尝试模拟泛型方法的返回类型以匹配特定的具体类型,但我似乎无法让转换工作:

    public T Get<T>(string key)
    {
        if (typeof(T) == typeof(GenericIsAuthenticatedResponse) && key == "1234")
            return GetGenericIsAuthenticatedResponse();

        return default(T);
    }

    private static GenericIsAuthenticatedResponse GetGenericIsAuthenticatedResponse()
    {
       return new GenericIsAuthenticatedResponse
        {
            AuthCode = "1234",
            Email = "email@email.com"
        };
    }

所以我的问题是如何让模拟方法返回 GenericIsAuthenticatedResponse?

【问题讨论】:

  • 为什么在这种情况下你希望你的方法是通用的?
  • 因为它用于各种不同的类型,我只测试一个非常具体的场景。
  • 假设 T 在测试中始终为GenericIsAuthenticatedResponse,您可以简单地将返回值转换为T,然后再返回。
  • 试试return (T)(object)GetGenericIsAuthenticatedResponse();

标签: c# .net unit-testing generics mocking


【解决方案1】:

这不起作用,因为泛型是如何工作的。如果要返回特定类型,需要为T提供过滤器:

public T Get<T>(string key) where T: GenericIsAuthenticatedResponse 

否则,不要使用泛型作为返回类型:

public object Get<T>(string key)
{
    if (typeof(T) == typeof(GenericIsAuthenticatedResponse) && key == "1234")
        return GetGenericIsAuthenticatedResponse();

    return default(T);
}

如果您完全确定 T 将是 GenericIsAuthenticatedResponse(假设这是一个测试),您可以这样做:

public T Get<T>(string key)
{
    if (typeof(T) == typeof(GenericIsAuthenticatedResponse) && key == "1234")
        return (T)GetGenericIsAuthenticatedResponse();

    return default(T);
}

【讨论】:

  • 是的,谢谢,但我不想仅仅为了满足 1 个特定的测试用例而改变方法。
【解决方案2】:

我最终应用了一些横向思考(或根据您的 POV 进行了调整)和序列化/反序列化的 Json 来实现这一目标:

   public T Get<T>(string key)
    {
        if (typeof(T) == typeof(GenericIsAuthenticatedResponse) && key == "1234")
            return JsonConvert.DeserializeObject<T>(GetGenericIsAuthenticatedResponse());

        return default(T);
    }

    private static string GetGenericIsAuthenticatedResponse()
    {
        var r = new GenericIsAuthenticatedResponse
        {
            Username = "email.email.com",
            AuthCode = "1234"
        };

        return JsonConvert.SerializeObject(r);
    }

【讨论】:

  • 如果T 不是GenericIsAuthenticatedResponse,这将失败。如果是这种情况,您可以直接完成(T)GetGenericIsAuthenticatedResponse()
  • 你不需要序列化和反序列化一个对象只是为了转换一个引用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-17
  • 2016-12-24
  • 2021-02-12
  • 2021-05-18
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
相关资源
最近更新 更多