JustMock和XUnit - 在模拟SQLConnection

时间:2017-12-11 20:06:38

标签: c# unit-testing justmock

我正在为我的派生类测试模拟SQLConnection,并注意到它似乎使XUnit(?)忽略了结果。

重现行为的示例:

using System.Data.SqlClient;
using System.Threading.Tasks;
using Telerik.JustMock;
using Xunit;

namespace JustMockTesting {

    public abstract class BaseClass {
        protected abstract Task<int> ConnectTask();
    }

    public class Derived1 : BaseClass {
        protected override Task<int> ConnectTask() {
            return Task.FromResult( 1 );
        }
    }

    public class Derived2 : BaseClass {
        protected override Task<int> ConnectTask() {
            return Task.FromResult( 2 );
        }
    }

    public class Derived1Tests {
        private Derived1 derived1;

        public Derived1Tests() {
            derived1 = Mock.Create<Derived1>();
        }

        [Fact]
        public void Test1() {
            Mock.NonPublic.Arrange( derived1, "ConnectTask" ).CallOriginal();
            Mock.Arrange( () => Mock.Create<SqlConnection>().Open() ).DoNothing();

            Task<int> i = (Task<int>)new PrivateAccessor( derived1 ).CallMethod( "ConnectTask" );

            Assert.Equal( 1, i.Result );
        }
    }

    public class Derived2Tests {
        private Derived2 derived2;

        public Derived2Tests() {
            derived2 = Mock.Create<Derived2>();
        }

        [Fact]
        public void Test2() {
            Mock.NonPublic.Arrange( derived2, "ConnectTask" ).CallOriginal();
            //Mock.Arrange( () => Mock.Create<SqlConnection>().Open() ).DoNothing();

            Task<int> i = (Task<int>)new PrivateAccessor( derived2 ).CallMethod( "ConnectTask" );

            Assert.Equal( 2, i.Result );
        }
    }
}

环境

  • VS 2017 ver。 15.3.4
  • xunit和xunit.runner.visualstudio ver。 2.3.1
  • JustMock ver。 2017.3.913.1

首饰

  • 没有模拟SQL连接的测试将运行但结果似乎被忽略。如果将鼠标悬停在测试图标上,则会说它在上次测试运行中没有执行。将该行添加到模拟SQLConnection将使另一个测试运行。
  • 如果您将派生类方法更改为返回int而不是Task<int>,则似乎不会出现此问题。
  • 有时会抛出以下异常(为了保持帖子简短,省略了其余的跟踪):

    System.ArgumentException : 'this' type cannot be an interface itself.
    Stack Trace:
         at System.RuntimeTypeHandle.VerifyInterfaceIsImplemented(RuntimeTypeHandle handle, RuntimeTypeHandle interfaceHandle)
         at System.RuntimeTypeHandle.VerifyInterfaceIsImplemented(RuntimeTypeHandle interfaceHandle)
    

不确定这是JustMock还是XUnit的问题。谷歌搜索没有提供太多信息,所以任何见解都会受到赞赏。

更新1 - 基于@Nkosi评论的示例

public abstract class BaseClass {
    protected abstract Task<bool> ConnectTask();
}

public class Derived1 : BaseClass {
    protected async override Task<bool> ConnectTask() {
        return await Task.FromResult( true );
    }
}

public class Derived2 : BaseClass {
    protected async override Task<bool> ConnectTask() {
        using ( SqlConnection conn = new SqlConnection( "someConnectionString" ) ) {
            try {
                conn.Open();
                return await Task.FromResult( true );
            } catch  {
                return await Task.FromResult( false );
            }
        }
    }
}

public class Derived1Tests {
    private Derived1 derived1;

    public Derived1Tests() {
        derived1 = Mock.Create<Derived1>();
    }

    [Fact]
    public async Task Test1() {
        Mock.NonPublic.Arrange( derived1, "ConnectTask" ).CallOriginal();

        //SqlConnection mockSqlConnection = Mock.Create<SqlConnection>();
        //Mock.Arrange( () => mockSqlConnection.Open() ).DoNothing();
        //Mock.Arrange( () => mockSqlConnection.Close() ).DoNothing();
        //Mock.Arrange( () => new SqlConnection( Arg.IsAny<string>() ) ).Returns( mockSqlConnection );

        bool b = await (Task<bool>)new PrivateAccessor( derived1 ).CallMethod( "ConnectTask" );

        Assert.True( b );
    }
}

public class Derived2Tests {
    private Derived2 derived2;

    public Derived2Tests() {
        derived2 = Mock.Create<Derived2>();
    }

    [Fact]
    public async Task Test2() {
        Mock.NonPublic.Arrange( derived2, "ConnectTask" ).CallOriginal();

        SqlConnection mockSqlConnection = Mock.Create<SqlConnection>();
        Mock.Arrange( () => mockSqlConnection.Open() ).DoNothing();
        Mock.Arrange( () => mockSqlConnection.Close() ).DoNothing();
        Mock.Arrange( () => new SqlConnection( Arg.IsAny<string>() ) ).Returns( mockSqlConnection );

        bool b = await (Task<bool>)new PrivateAccessor( derived2 ).CallMethod( "ConnectTask" );

        Assert.True( b );
    }
}

首饰

  • 在切换到async / await之后,测试似乎没有完成。在向它们添加断点时会触发assert语句,但是在逐步执行断言后测试会继续运行。
  • 将模拟代码添加到其他测试中似乎现在没什么区别,两个测试都会无限期地运行。

0 个答案:

没有答案