【问题标题】:Unit test a static method that calls a static method using moq单元测试使用 moq 调用静态方法的静态方法
【发布时间】:2011-09-14 09:47:44
【问题描述】:

如题,代码如下

internal static class ThumbnailPresentationLogic
    {
        public static string GetThumbnailUrl(List<Image> images)
        {
            if (images == null || images.FirstOrDefault() == null)
            {
                return ImageRetrievalConfiguration.MiniDefaultImageFullUrl;
            }

            Image latestImage = (from image in images
                                 orderby image.CreatedDate descending
                                 select image).First();

            Uri fullUrl;

            return 
                Uri.TryCreate(new Uri(ImageRetrievalConfiguration.GetConfig().ImageRepositoryName), latestImage.FileName,
                    out fullUrl)
                    ? fullUrl.AbsoluteUri
                    : ImageRetrievalConfiguration.MiniDefaultImageFullUrl;
        }
    }

我不希望单元测试通过ImageRetrievalConfiguration 类中的任何方法,那么如何模拟ImageRetrievalConfiguration 并将其传递给ThumbnailPresentationLogic 类??

【问题讨论】:

    标签: c# unit-testing nunit moq static-methods


    【解决方案1】:

    您如何将方法分成两部分 - 其中一个采用“基本 URI”和“默认 Url”,其中一个没有:

    internal static class ThumbnailPresentationLogic
    {
        public static string GetThumbnailUrl(List<Image> images)
        {
            return GetThumbnailUrl(images,
               new Uri(ImageRetrievalConfiguration.GetConfig().ImageRepositoryName),
               ImageRetrievalConfiguration.MiniDefaultImageFullUrl);
        }
    
        public static string GetThumbnailUrl(List<Image> images, Uri baseUri,
            string defaultImageFullUrl)
        {
            if (images == null || images.FirstOrDefault() == null)
            {
                return defaultImageFullUrl;
            }
    
            Image latestImage = (from image in images
                                 orderby image.CreatedDate descending
                                 select image).First();
    
            Uri fullUrl;
    
            return 
                Uri.TryCreate(baseUri, latestImage.FileName, out fullUrl)
                    ? fullUrl.AbsoluteUri
                    : defaultImageFullUrl;
        }
    }
    

    然后你可以在“三参数”重载中测试逻辑,但是公共方法实际上并不包含任何逻辑。您不会获得 100% 的覆盖率,但您将能够测试所涉及的真正逻辑。

    【讨论】:

      【解决方案2】:

      你不能用 Moq 做到这一点,因为你需要拦截对这个静态类的方法的调用,这是所有“普通”模拟框架都无法实现的,因为它们纯粹是使用类型继承来工作的,自动代码生成和类似的东西。
      然而,拦截对静态方法的调用需要其他机制。
      可以使用Moles 拦截对 .NET 框架静态类的调用。我不确定它是否适用于您自己的静态类。
      TypeMock Isolator 适用于所有静态类,但它不是免费的。

      但是,我真的认为,您应该重新考虑您的架构。

      【讨论】:

        【解决方案3】:

        我不确定是否可以通过 Moq 我使用 Rhino Mocks。在这种情况下,我通常做的是使用 Spring.NET 并提供一个替代模拟,我在测试中调用它与生产中的模拟相对应。这对我来说非常有效,尤其是在使用外部 Web 服务、数据源或您提出的情况的领域。

        然后您单独测试 ImageRetrievalConfiguration 并确保它按预期工作。 MockImageRetrievalConfiguration 可以根据您希望它在测试环境中的反应方式返回结果。这将通过模拟的灵活性最大化您的测试收敛。

            internal static class SpringApplicationContext
            {
                private static IApplicationContext applicationContext = null;
        
                static SpringApplicationContext()
                {
                    applicationContext = ContextRegistry.GetContext();
                }
        
                public static IApplicationContext ApplicationContext
                {
                    get { return applicationContext; }
                }
            }
        
           public interface IImageRetrievalData
           {
               string ImageRepositoryName{get;set;}
           }    
        
        public interface IImageRetrievalConfiguration    
        {
             IImageRetrievalData GetConfig();
        }
        
        public class MockImageRetrievalConfiguration : IImageRetrievalConfiguration    
        {    
            public IImageRetrievalData GetConfig()
             {
                 //mock implementation
             }
        }
        
        public class ImageRetrievalConfiguration : IImageRetrievalConfiguration    
        {
        
            public IImageRetrievalData GetConfig()
             {
                //Concrete implementation
             }
        }
        
        
        
        //your code
        internal static class ThumbnailPresentationLogic     
        {         
                  public static string GetThumbnailUrl(List<Image> images)
                  {             
                    if (images == null || images.FirstOrDefault() == null)                                         
                    {                 
                        return ImageRetrievalConfiguration.MiniDefaultImageFullUrl;             
                    }              
                    Image latestImage = (from image in images orderby image.CreatedDate descending select image).First();              
                    Uri fullUrl;   
        
        //Spring 
                        IImageRetrievalConfiguration imageRetrievalConfig = (IImageRetrievalConfiguration)            SpringApplicationContext.ApplicationContext["ImageRetrievalConfiguration"];
        
        
        
                    return Uri.TryCreate(new Uri(imageRetrievalConfig.GetConfig().ImageRepositoryName), latestImage.FileName, out fullUrl) ? fullUrl.AbsoluteUri : ImageRetrievalConfiguration.MiniDefaultImageFullUrl;         
                  }     
        } 
        

        //这将是您的测试配置

          <spring>
            <context>
              <resource uri="config://spring/objects" />
            </context>
            <objects xmlns="http://www.springframework.net">
              <object name="ImageRetrievalConfiguration" type="Tests.MockImageRetrievalConfiguration, Tests" singleton="false" />
            </objects>
          </spring>
        

        //这将是您的生产配置

          <spring>
            <context>
              <resource uri="config://spring/objects" />
            </context>
            <objects xmlns="http://www.springframework.net">
              <object name="ImageRetrievalConfiguration" type="Web.ImageRetrievalConfiguration , Web" singleton="false" />
            </objects>
          </spring>
        

        您可以从http://www.springframework.net/下载Spring.NET框架

        【讨论】:

        • 我已经针对你提到的情况修改了代码。这将导致在测试中不调用具体实现,但仍然允许它是可测试的。
        猜你喜欢
        • 1970-01-01
        • 2020-09-06
        • 2019-05-11
        • 2011-12-24
        • 2011-08-23
        • 1970-01-01
        • 2022-01-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多