针对 SQL 服务器数据的错误 运行 XUnit 测试 - 为 Tests.UnitTest1.Test1 上的 Tests.SqlServerDataAttribute 指定的数据发现器不存在
Error running XUnit Test against SQL Server Data - Data discoverer specified for Tests.SqlServerDataAttribute on Tests.UnitTest1.Test1 does not exist
我在使用 xunit 进行一些集成测试时遇到问题 运行。我有一个将数据插入 MSSQL 数据库的过程,然后我想 运行 对这些数据进行一些测试。
我正在使用 .Net Core 和 xunit 进行测试,并使用此处 https://github.com/xunit/samples.xunit/tree/main/SqlDataExample 中的示例来创建这些。
我收到的错误是在 Tests.UnitTest1.Test1 上为 Tests.SqlServerDataAttribute 指定的数据发现器不存在。
相关代码片段如下:
[SqlServerData("ServerIp", "DbName", "DbUser","DbPwd", "SELECT name FROM Users")]
public void Test1(string name)
{
Assert.Equal("T C One", name);
}
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
namespace Tests
{
/// <summary>
/// Provides a data source for a data theory, with the data coming a Microsoft SQL Server.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
[SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification = "The values are available indirectly on the base class.")]
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "This attribute is designed as an extensibility point.")]
public class SqlServerDataAttribute : OleDbDataAttribute
{
const string sqlWithTrust =
"Provider=SQLOLEDB; Data Source={0}; Initial Catalog={1}; Integrated Security=SSPI;";
const string sqlWithUser =
"Provider=SQLOLEDB; Data Source={0}; Initial Catalog={1}; User ID={2}; Password={3};";
/// <summary>
/// Creates a new instance of <see cref="SqlServerDataAttribute"/>, using a trusted connection.
/// </summary>
/// <param name="serverName">The server name of the Microsoft SQL Server</param>
/// <param name="databaseName">The database name</param>
/// <param name="selectStatement">The SQL SELECT statement to return the data for the data theory</param>
public SqlServerDataAttribute(string serverName,
string databaseName,
string selectStatement)
: base(String.Format(CultureInfo.InvariantCulture, sqlWithTrust, serverName, databaseName), selectStatement)
{
}
/// <summary>
/// Creates a new instance of <see cref="SqlServerDataAttribute"/>, using the provided username and password.
/// </summary>
/// <param name="serverName">The server name of the Microsoft SQL Server</param>
/// <param name="databaseName">The database name</param>
/// <param name="userName">The username for the server</param>
/// <param name="password">The password for the server</param>
/// <param name="selectStatement">The SQL SELECT statement to return the data for the data theory</param>
public SqlServerDataAttribute(string serverName,
string databaseName,
string userName,
string password,
string selectStatement)
: base(String.Format(CultureInfo.InvariantCulture, sqlWithUser, serverName, databaseName, userName, password),
selectStatement)
{ }
}
}
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using Xunit.Sdk;
namespace Tests
{
/// <summary>
/// Represents an implementation of <see cref="DataAttribute"/> which uses an
/// instance of <see cref="IDataAdapter"/> to get the data for a <see cref="TheoryAttribute"/>
/// decorated test method.
/// </summary>
[DataDiscoverer("DataAdapterDataAttributeDiscoverer", "Tests")]
public abstract class DataAdapterDataAttribute : DataAttribute
{
/// <summary>
/// Gets the data adapter to be used to retrieve the test data.
/// </summary>
protected abstract IDataAdapter DataAdapter { get; }
/// <summary>
/// Returns <c>true</c> if the data attribute wants to enumerate data during discovery. By
/// default, this attribute assumes that data enumeration is too expensive to do during
/// discovery, and therefore defaults to <c>false</c>.
/// </summary>
public bool EnableDiscoveryEnumeration { get; set; }
/// <inheritdoc/>
public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest)
{
DataSet dataSet = new DataSet();
IDataAdapter adapter = DataAdapter;
try
{
adapter.Fill(dataSet);
foreach (DataRow row in dataSet.Tables[0].Rows)
yield return ConvertParameters(row.ItemArray);
}
finally
{
IDisposable disposable = adapter as IDisposable;
if (disposable != null)
disposable.Dispose();
}
}
object[] ConvertParameters(object[] values)
{
object[] result = new object[values.Length];
for (int idx = 0; idx < values.Length; idx++)
result[idx] = ConvertParameter(values[idx]);
return result;
}
/// <summary>
/// Converts a parameter to its destination parameter type, if necessary.
/// </summary>
/// <param name="parameter">The parameter value</param>
/// <returns>The converted parameter value</returns>
protected virtual object ConvertParameter(object parameter)
{
if (parameter is DBNull)
return null;
return parameter;
}
}
}
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Tests
{
public class DataAdapterDataAttributeDiscoverer : DataDiscoverer
{
public override bool SupportsDiscoveryEnumeration(IAttributeInfo dataAttribute, IMethodInfo testMethod)
=> dataAttribute.GetNamedArgument<bool>("EnableDiscoveryEnumeration");
}
}
我已经验证了连接字符串和对数据库的查询,并且在尝试 运行 测试时我在数据库上有 运行 SQL Profiler 但没有任何结果数据库。
知道我错过了什么吗?
我设法找到了问题所在。您需要 DataDiscoverer 上的完全限定类型名称:
[DataDiscoverer("Tests.DataAdapterDataAttributeDiscoverer", "Tests")]
我在使用 xunit 进行一些集成测试时遇到问题 运行。我有一个将数据插入 MSSQL 数据库的过程,然后我想 运行 对这些数据进行一些测试。
我正在使用 .Net Core 和 xunit 进行测试,并使用此处 https://github.com/xunit/samples.xunit/tree/main/SqlDataExample 中的示例来创建这些。
我收到的错误是在 Tests.UnitTest1.Test1 上为 Tests.SqlServerDataAttribute 指定的数据发现器不存在。
相关代码片段如下:
[SqlServerData("ServerIp", "DbName", "DbUser","DbPwd", "SELECT name FROM Users")]
public void Test1(string name)
{
Assert.Equal("T C One", name);
}
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
namespace Tests
{
/// <summary>
/// Provides a data source for a data theory, with the data coming a Microsoft SQL Server.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
[SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification = "The values are available indirectly on the base class.")]
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "This attribute is designed as an extensibility point.")]
public class SqlServerDataAttribute : OleDbDataAttribute
{
const string sqlWithTrust =
"Provider=SQLOLEDB; Data Source={0}; Initial Catalog={1}; Integrated Security=SSPI;";
const string sqlWithUser =
"Provider=SQLOLEDB; Data Source={0}; Initial Catalog={1}; User ID={2}; Password={3};";
/// <summary>
/// Creates a new instance of <see cref="SqlServerDataAttribute"/>, using a trusted connection.
/// </summary>
/// <param name="serverName">The server name of the Microsoft SQL Server</param>
/// <param name="databaseName">The database name</param>
/// <param name="selectStatement">The SQL SELECT statement to return the data for the data theory</param>
public SqlServerDataAttribute(string serverName,
string databaseName,
string selectStatement)
: base(String.Format(CultureInfo.InvariantCulture, sqlWithTrust, serverName, databaseName), selectStatement)
{
}
/// <summary>
/// Creates a new instance of <see cref="SqlServerDataAttribute"/>, using the provided username and password.
/// </summary>
/// <param name="serverName">The server name of the Microsoft SQL Server</param>
/// <param name="databaseName">The database name</param>
/// <param name="userName">The username for the server</param>
/// <param name="password">The password for the server</param>
/// <param name="selectStatement">The SQL SELECT statement to return the data for the data theory</param>
public SqlServerDataAttribute(string serverName,
string databaseName,
string userName,
string password,
string selectStatement)
: base(String.Format(CultureInfo.InvariantCulture, sqlWithUser, serverName, databaseName, userName, password),
selectStatement)
{ }
}
}
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using Xunit.Sdk;
namespace Tests
{
/// <summary>
/// Represents an implementation of <see cref="DataAttribute"/> which uses an
/// instance of <see cref="IDataAdapter"/> to get the data for a <see cref="TheoryAttribute"/>
/// decorated test method.
/// </summary>
[DataDiscoverer("DataAdapterDataAttributeDiscoverer", "Tests")]
public abstract class DataAdapterDataAttribute : DataAttribute
{
/// <summary>
/// Gets the data adapter to be used to retrieve the test data.
/// </summary>
protected abstract IDataAdapter DataAdapter { get; }
/// <summary>
/// Returns <c>true</c> if the data attribute wants to enumerate data during discovery. By
/// default, this attribute assumes that data enumeration is too expensive to do during
/// discovery, and therefore defaults to <c>false</c>.
/// </summary>
public bool EnableDiscoveryEnumeration { get; set; }
/// <inheritdoc/>
public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest)
{
DataSet dataSet = new DataSet();
IDataAdapter adapter = DataAdapter;
try
{
adapter.Fill(dataSet);
foreach (DataRow row in dataSet.Tables[0].Rows)
yield return ConvertParameters(row.ItemArray);
}
finally
{
IDisposable disposable = adapter as IDisposable;
if (disposable != null)
disposable.Dispose();
}
}
object[] ConvertParameters(object[] values)
{
object[] result = new object[values.Length];
for (int idx = 0; idx < values.Length; idx++)
result[idx] = ConvertParameter(values[idx]);
return result;
}
/// <summary>
/// Converts a parameter to its destination parameter type, if necessary.
/// </summary>
/// <param name="parameter">The parameter value</param>
/// <returns>The converted parameter value</returns>
protected virtual object ConvertParameter(object parameter)
{
if (parameter is DBNull)
return null;
return parameter;
}
}
}
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Tests
{
public class DataAdapterDataAttributeDiscoverer : DataDiscoverer
{
public override bool SupportsDiscoveryEnumeration(IAttributeInfo dataAttribute, IMethodInfo testMethod)
=> dataAttribute.GetNamedArgument<bool>("EnableDiscoveryEnumeration");
}
}
我已经验证了连接字符串和对数据库的查询,并且在尝试 运行 测试时我在数据库上有 运行 SQL Profiler 但没有任何结果数据库。
知道我错过了什么吗?
我设法找到了问题所在。您需要 DataDiscoverer 上的完全限定类型名称:
[DataDiscoverer("Tests.DataAdapterDataAttributeDiscoverer", "Tests")]