1

我正在为派生类测试模拟 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 版 15.3.4
  • xunit 和 xunit.runner.visualstudio 版本。2.3.1
  • JustMock 版本。2017.3.913.1

发现

  • 没有模拟 SQL 连接的测试将运行,但结果似乎被忽略了。如果您将鼠标悬停在测试图标上,它会说它在上次测试运行中没有被执行。将行添加到模拟 SQLConnection 将使其他测试运行。
  • 如果将派生类方法更改为 returnint而不是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 后,测试现在似乎没有完成运行。断言语句在向它们添加断点时会受到影响,但测试会在跨过断言后继续运行。
  • 将模拟代码添加到另一个测试现在似乎没有什么不同,两个测试都将无限期地运行。
4

0 回答 0