测试驱动开发例子学习-Using TDD with ADO.NET
|
来源 :博客园 使用智能客户端 http://www.cnblogs.com/jasonw/archive/2004/10/10/50659.html
1. 连接字符串的测试驱动范例:
DataBase -SQL Server 2000: using System; using System.Data; using System.Data.SqlClient; namespace DataAccessLayer {
public class ArtistGateway {
private SqlDataAdapter adapter; private SqlConnection connection; private SqlCommand command; private SqlCommandBuilder builder; public ArtistGateway(SqlConnection connection) {
this.connection = connection; command = new SqlCommand( "select id,name from artist where id = @id", connection); command.Parameters.Add("@id",SqlDbType.BigInt);
adapter = new SqlDataAdapter(command); builder = new SqlCommandBuilder(adapter); } public long Insert( RecordingDataSet recordingDataSet,string artistName) {
long artistId = GetNextId(recordingDataSet.Artists.TableName); RecordingDataSet.Artist artistRow = recordingDataSet.Artists.NewArtist(); artistRow.Id = artistId; artistRow.Name = artistName; recordingDataSet.Artists.AddArtist(artistRow); adapter.Update(recordingDataSet, recordingDataSet.Artists.TableName); return artistId; } public RecordingDataSet.Artist FindById(long artistId,RecordingDataSet recordingDataSet) {
command.Parameters["@id"].Value = artistId; adapter.Fill(recordingDataSet, recordingDataSet.Artists.TableName); DataRow[] rows = recordingDataSet.Artists.Select( String.Format("id={0}",artistId));
if(rows.Length < 1) return null; return (RecordingDataSet.Artist)rows[0]; } public long GetNextId(string tableName) {
SqlTransaction transaction = connection.BeginTransaction( IsolationLevel.Serializable,"GenerateId"); SqlCommand selectCommand = new SqlCommand( "select nextId from PKSequence where tableName = @tableName", connection,transaction); selectCommand.Parameters.Add("@tableName",
SqlDbType.VarChar).Value=tableName; long nextId = (long)selectCommand.ExecuteScalar(); SqlCommand updateCommand = new SqlCommand( "update PKSequence set nextId = @nextId where tableName=@tableName", connection,transaction); updateCommand.Parameters.Add("@tableName",
SqlDbType.VarChar).Value=tableName; updateCommand.Parameters.Add("@nextId",
SqlDbType.BigInt).Value=nextId+1; updateCommand.ExecuteNonQuery(); transaction.Commit(); return nextId; }4. ArtistFixture.cs 数据访问层代理类的测试用例 using System; using System.Configuration; using System.Data; using System.Data.SqlClient; using DataAccessLayer; using NUnit.Framework; [TestFixture] public class ArtistFixture {
[Test] public void RetrieveArtistFromDatabase() {
string artistName = "Artist"; SqlConnection connection = new SqlConnection( ConfigurationSettings.AppSettings.Get( "Catalog.Connection")); connection.Open(); ArtistGateway gateway = new ArtistGateway(connection); long artistId = gateway.Insert(new RecordingDataSet(),artistName); RecordingDataSet loadedFromDB = new RecordingDataSet(); RecordingDataSet.Artist loadedArtist = gateway.FindById(artistId,loadedFromDB); Assert.AreEqual(artistId,loadedArtist.Id); Assert.AreEqual(artistName,loadedArtist.Name); gateway.Delete(loadedFromDB,artistId); //删除功能的驱动 connection.Close(); } }5. 删除驱动所形成的实现代码: public void Delete(RecordingDataSet recordingDataSet,long artistId) { RecordingDataSet.Artist loadedArtist = FindById(artistId,recordingDataSet); loadedArtist.Delete(); adapter.Update(recordingDataSet, recordingDataSet.Artists.TableName); } 6. 有了完整的测试用例,以及实现的代码,可以进行重构: //首先优化测试的代码: [TestFixture] public class ArtistFixture {
private static readonly string artistName = "Artist"; private SqlConnection connection; private ArtistGateway gateway; private RecordingDataSet recordingDataSet; private long artistId; [SetUp] public void SetUp() {
connection = new SqlConnection( ConfigurationSettings.AppSettings.Get( "Catalog.Connection")); connection.Open(); recordingDataSet = new RecordingDataSet(); gateway = new ArtistGateway(connection); artistId = gateway.Insert(recordingDataSet,artistName); } [TearDown] public void TearDown() {
gateway.Delete(recordingDataSet,artistId); connection.Close(); } [Test] public void RetrieveArtistFromDatabase() {
RecordingDataSet loadedFromDB = new RecordingDataSet(); RecordingDataSet.Artist loadedArtist = gateway.FindById(artistId,loadedArtist.Name); } [Test] public void DeleteArtistFromDatabase() {
RecordingDataSet emptyDataSet = new RecordingDataSet(); long deletedArtistId = gateway.Insert(emptyDataSet,"Deleted Artist"); gateway.Delete(emptyDataSet,deletedArtistId); RecordingDataSet.Artist deleletedArtist = gateway.FindById(deletedArtistId,emptyDataSet); Assert.IsNull(deleletedArtist); } }7. 在重构的基础上加入更新方法:. [Test] public void UpdateArtistInDatabase() {
RecordingDataSet.Artist artist = recordingDataSet.Artists[0]; artist.Name = "Modified Name"; gateway.Update(recordingDataSet); RecordingDataSet updatedDataSet = new RecordingDataSet(); RecordingDataSet.Artist updatedArtist = gateway.FindById(artistId,updatedDataSet); Assert.AreEqual("Modified Name",updatedArtist.Name);
}//The following is the implementation of Update: public void Update(RecordingDataSet recordingDataSet) {
adapter.Update(recordingDataSet, recordingDataSet.Artists.TableName); }8. Genre Gateway 另一个测试驱动的例子(类似于artists) [TestFixture] public class GenreFixture {
private static readonly string genreName = "Rock"; private SqlConnection connection; private GenreGateway gateway; private RecordingDataSet recordingDataSet; private long genreId; [SetUp] public void SetUp() {
connection = new SqlConnection( ConfigurationSettings.AppSettings.Get( "Catalog.Connection")); connection.Open(); recordingDataSet = new RecordingDataSet(); gateway = new GenreGateway(connection); genreId = gateway.Insert(recordingDataSet,genreName); } [TearDown] public void TearDown() {
gateway.Delete(recordingDataSet,genreId); connection.Close(); } [Test] public void RetrieveGenreFromDatabase() {
RecordingDataSet loadedFromDB = new RecordingDataSet(); RecordingDataSet.Genre loadedGenre = gateway.FindById(genreId,loadedFromDB); Assert.AreEqual(genreId,loadedGenre.Id); Assert.AreEqual(genreName,loadedGenre.Name); } }9. 实现部分Genre Gateway: public class GenreGateway {
private SqlDataAdapter adapter; private SqlConnection connection; private SqlCommand command; private SqlCommandBuilder builder; public GenreGateway(SqlConnection connection) {
this.connection = connection; command = new SqlCommand( "select id,name from Genre where id = @id",SqlDbType.BigInt); adapter = new SqlDataAdapter(command); builder = new SqlCommandBuilder(adapter); } public long Insert(RecordingDataSet recordingDataSet, string genreName) {
long genreId = GetNextId(recordingDataSet.Genres.TableName); RecordingDataSet.Genre genreRow = recordingDataSet.Genres.NewGenre(); genreRow.Id = genreId; genreRow.Name = genreName; recordingDataSet.Genres.AddGenre(genreRow); adapter.Update(recordingDataSet, recordingDataSet.Genres.TableName); return genreId; } public RecordingDataSet.Genre FindById(long genreId,RecordingDataSet recordingDataSet) {
command.Parameters["@id"].Value = genreId; adapter.Fill(recordingDataSet, recordingDataSet.Genres.TableName); DataRow[] rows = recordingDataSet.Genres.Select( String.Format("id={0}",genreId));
if(rows.Length < 1) return null; return (RecordingDataSet.Genre)rows[0]; } public void Delete(RecordingDataSet recordingDataSet, long genreId) {
RecordingDataSet.Genre loadedGenre = FindById(genreId,recordingDataSet); loadedGenre.Delete(); adapter.Update(recordingDataSet, recordingDataSet.Genres.TableName); } public long GetNextId(string tableName) { /* same as in ArtistGateway */ }
}10.获取下一个ID [TestFixture] public class IdGeneratorFixture {
private SqlConnection connection; [SetUp] public void OpenConnection() {
connection = new SqlConnection( ConfigurationSettings.AppSettings.Get( "Catalog.Connection")); connection.Open(); } [Test] public void GetNextIdIncrement() {
SqlCommand sqlCommand = new SqlCommand( "select nextId from PKSequence where tableName=@tableName", connection); sqlCommand.Parameters.Add( "@tableName",SqlDbType.VarChar).Value="Artist"; long nextId = (long)sqlCommand.ExecuteScalar(); long nextIdFromGenerator = IdGenerator.GetNextId("Artist",connection);
Assert.AreEqual(nextId,nextIdFromGenerator); nextId = (long)sqlCommand.ExecuteScalar(); Assert.AreEqual(nextId,nextIdFromGenerator + 1); } [TearDown] public void CloseConnection() {
connection.Close(); } }//实现部分 public class IdGenerator {
public static long GetNextId(string tableName, SqlConnection connection) {
SqlTransaction transaction = connection.BeginTransaction( IsolationLevel.Serializable,"GenerateId"); SqlCommand selectCommand = new SqlCommand( "select nextId from PKSequence where tableName = @tableName", SqlDbType.VarChar).Value=tableName; long nextId = (long)selectCommand.ExecuteScalar(); SqlCommand updateCommand = new SqlCommand( "update PKSequence set nextId = @nextId where tableName=@tableName",SqlDbType.VarChar).Value=tableName; updateCommand.Parameters.Add("@nextId",SqlDbType.BigInt).Value=nextId+1;
updateCommand.ExecuteNonQuery(); transaction.Commit(); return nextId; } }11.IdGeneratorFixture.cs优化过得实现: using System; using System.Configuration; using System.Data; using System.Data.SqlClient; using NUnit.Framework; using DataAccessLayer; [TestFixture] public class IdGeneratorFixture : ConnectionFixture {
[Test] public void GetNextIdIncrement() {
SqlCommand sqlCommand = new SqlCommand( "select nextId from PKSequence where tableName=@tableName", Connection); sqlCommand.Parameters.Add("@tableName",SqlDbType.VarChar).Value="Artist";
long nextId = (long)sqlCommand.ExecuteScalar(); long nextIdFromGenerator = IdGenerator.GetNextId("Artist",Connection);
Assert.AreEqual(nextId,nextIdFromGenerator + 1); } } (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
