我正在为我的派生类测试模拟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 );
}
}
}
环境
首饰
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 );
}
}
首饰