单元测试-测试替身

在讲Test Double以前,得先上搞清楚另外两个

  • SUT:System Under Test/Software Under Test 【待测程序】,在Unit Test角度下待测程序会是method

  • DOC:Depended-on Component【相依元件】,例如:成立订单函数,如果订单失败异常会写入log,log函数就是成立订单函数的DOC

    在实务上笔者在写单元测试的时候,因为SUT会去呼叫其他的物件也会呈现出SUT依赖DOC,
    在测试SUT势必会有DOC存在,搞得测试很复杂。

目前测试替身有五种Dummy Object、Test Stub、Test Spy、Fake Object与Mock Object
笔者目前是常用到Stub、Mock、Fake Object。

Dummy Objects用法:测试中必续传入的物件,实际上这些物件根本不会用到,只是为了能够调用背侧物件而必须传入的一个东西【目前没用到】。

Stub用法:回传固定的值。

    public class StubUserRepository : IUserRepository
    {
        public string GetUserRole(string username)
        {
            return "administrator";
        }

        public List<User> GetAllUsers()
        {
            return new List<User>()
            {
                new User{ Role = "administrator", Name = "admin"},
            };
        }
    }
    public interface IUserRepository
    {
        string GetUserRole(string username);
    }

    public class User
    {
        public string Name { get; set; }
        public string Role { get; set; }
    }

Fake用法:接近提供原始物件较简单实作方式。

    public class FakeUserRepository : IUserRepository
    {
        public string GetUserRole(string username)
        {
            if (username == "admin")
                return "administrator";
            else
                return "contributor";
        }
    }

    public interface IUserRepository
    {
        string GetUserRole(string username);
    }

Spy用法:把spy想成是一个偷偷纪录呼叫过程的Stub,宣告被spy的物件,某个函式被呼叫的时候回传某个值。

    public class SpyUserStore : IUserRepository
    {
        private static int Counter { get; set; }

        public SpyUserStore()
        {
            Counter = 0;
        }

        public string GetUserRole(string username)
        {

            if (Counter >= 1)
                throw new Exception("Function called more than once");

            Counter++;

            if (username == "admin")
                return "administrator";
            else
                return "contributor";
        }
    }

Mock用法:用动态程序方式、提供类似Dummy,Stub,Spy功能

   var _memberRepository = Substitute.For<IMemberRepository>();
   var _memberService = new MemberService(_memberRepository);
   var _setReturnMember = new Member()
        {
           UserId = "test001",
           Password = "test001",
           Name = "test",
           Email = "[email protected]"
        };
   _memberRepository.GetByMember(userid,password).Returns(_setReturnMember);

最後总结一下,测试替身可以解决单元测试的那些问题?

  1. 测试替身是为了解决不用真的使用DOC
  2. 可以提升测试执行速度,避免速度太慢

另外其实在真的写测试,也不用太在意你是用哪一个测试替身...

参考来源

  1. 搞笑谈软工-测试替身
  2. jyt0532's Blog-测试替身

<<:  Leet Code 4. Running Sum

>>:  繁体转换简体

序章

大家好 继上次介绍的环控系统後本次要介绍如何将资料在DASHBORAD上将储存的资料用不同方式显示 ...

Day 19: Behavioral patterns - Command

目的 将行为拆成请求与执行两个区块,请求的部分独自封装成物件,执行的部分则交由专门负责执行的物件。 ...

Day-13 ConstraintLayout

ConstraintLayout(约束布局) ConstraintLayout为Android St...

[第六天]从0开始的UnityAR手机游戏开发-如何汇入Unity Package到Unity和Unity使用Vuforia插件的基本设置

Unity Package汇入方式 Unity Package汇入Unity有以下3种方式 双击两...

Leetcode: 210. Course Schedule II | 含C++笔记

Course Schedule I的延伸,这次要排出课程顺序。 思路 有大概想到去找node的顺序跟...