উপহাস এবং ইউনিট পরীক্ষার জন্য যখন প্রয়োজন হয় তখন স্কেলএক্সেপশন কীভাবে ছুঁড়ে ফেলা যায়?


86

আমি আমার প্রকল্পে কিছু ব্যতিক্রম পরীক্ষা করার চেষ্টা করছি এবং আমার ধরা ব্যতিক্রমগুলির মধ্যে একটি SQlException

দেখে মনে হচ্ছে আপনি যেতে পারবেন না new SqlException()তাই আমি নিশ্চিত নই যে আমি কীভাবে একটি ব্যতিক্রম ছুঁড়ে ফেলব বিশেষত ডেটাবেস না বলে (এবং যেহেতু এটি ইউনিট পরীক্ষাগুলি এটি সাধারণত পরামর্শ দেওয়া হয় যে এটি ডাটাবেসটি ধীর না হওয়ার কারণে) not

আমি নুনিট এবং মোক ব্যবহার করছি, তবে কীভাবে এটি জাল করবেন তা আমি নিশ্চিত নই।

সকলের কাছে ADO.NET এর উপর ভিত্তি করে এমন কিছু উত্তরের প্রতিক্রিয়া জানিয়ে নোট করুন যে আমি লিনক থেকে এসকিএল ব্যবহার করছি। সুতরাং সেই জিনিসগুলি পর্দার আড়ালের মতো।

@ ম্যাটহ্যামিল্টনের অনুরোধ হিসাবে আরও তথ্য:

System.ArgumentException : Type to mock must be an interface or an abstract or non-sealed class.       
  at Moq.Mock`1.CheckParameters()
  at Moq.Mock`1..ctor(MockBehavior behavior, Object[] args)
  at Moq.Mock`1..ctor(MockBehavior behavior)
  at Moq.Mock`1..ctor()

প্রথম পংক্তিতে পোস্ট করা যখন এটি মকআপ দেওয়ার চেষ্টা করে

 var ex = new Mock<System.Data.SqlClient.SqlException>();
 ex.SetupGet(e => e.Message).Returns("Exception message");

তুমি ঠিক বলছো. আমি আমার উত্তর আপডেট করেছি, তবে সম্ভবত এটি এখন খুব বেশি সহায়ক নয়। DbException সম্ভবত ধরা ভাল ব্যতিক্রম যদিও, তাই এটি বিবেচনা করুন।
ম্যাট হ্যামিল্টন

উত্তরগুলি যা বাস্তবে কাজ করে তার ফলে বিভিন্ন রকমের ব্যতিক্রম বার্তা আসে। আপনার ঠিক কী ধরণের প্রয়োজন তা নির্ধারণ করা সহায়ক হতে পারে। উদাহরণস্বরূপ "আমার একটি স্কেলএক্সসেপশন দরকার যা ব্যতীত নম্বর 18487 রয়েছে, উল্লেখ করে নির্দিষ্ট পাসওয়ার্ডের মেয়াদ শেষ হয়ে গেছে" " ইউনিট পরীক্ষার জন্য এই জাতীয় সমাধানটি আরও উপযুক্ত বলে মনে হয়।
মাইক খ্রিস্টান

উত্তর:


9

যেহেতু আপনি লিনক থেকে এসকিএল ব্যবহার করছেন, তাই আপনি নুনিট এবং মোক ব্যবহার করে উল্লিখিত দৃশ্যের পরীক্ষার একটি নমুনা এখানে। আপনার ডেটা কনেক্সটেক্সের সঠিক বিবরণ এবং এটিতে আপনি কী সরবরাহ করেছেন তা আমি জানি না। আপনার প্রয়োজনের জন্য সম্পাদনা করুন।

আপনার একটি কাস্টম ক্লাসের সাথে ডেটা কনটেক্সটটি মোড়ানো প্রয়োজন, আপনি মাক দিয়ে ডেটা কনটেক্সটকে মক করতে পারবেন না। আপনি স্কেলএক্সসেপশনকেও উপহাস করতে পারবেন না, কারণ এটি সিল করে দেওয়া হয়েছে। আপনার নিজের ব্যাতিক্রম শ্রেণীর সাথে এটি মোড়ানো প্রয়োজন। এই দুটি জিনিস অর্জন করা কঠিন নয়।

আসুন আমাদের পরীক্ষা তৈরি করে শুরু করুন:

[Test]
public void FindBy_When_something_goes_wrong_Should_handle_the_CustomSqlException()
{
    var mockDataContextWrapper = new Mock<IDataContextWrapper>();
    mockDataContextWrapper.Setup(x => x.Table<User>()).Throws<CustomSqlException>();

    IUserResository userRespoistory = new UserRepository(mockDataContextWrapper.Object);
    // Now, because we have mocked everything and we are using dependency injection.
    // When FindBy is called, instead of getting a user, we will get a CustomSqlException
    // Now, inside of FindBy, wrap the call to the DataContextWrapper inside a try catch
    // and handle the exception, then test that you handled it, like mocking a logger, then passing it into the repository and verifying that logMessage was called
    User user = userRepository.FindBy(1);
}

আসুন পরীক্ষাটি বাস্তবায়িত করা যাক, প্রথমে আমাদের লিনকটি সিকিউএল কলগুলিতে সংগ্রহস্থল প্যাটার্নটি ব্যবহার করে গুটিয়ে রাখি:

public interface IUserRepository
{
    User FindBy(int id);
}

public class UserRepository : IUserRepository
{
    public IDataContextWrapper DataContextWrapper { get; protected set; }

    public UserRepository(IDataContextWrapper dataContextWrapper)
    {
        DataContextWrapper = dataContextWrapper;
    }

    public User FindBy(int id)
    {
        return DataContextWrapper.Table<User>().SingleOrDefault(u => u.UserID == id);
    }
}

এরপরে আইডাটা কনটেক্সট র‍্যাপারটি তৈরি করুন, আপনি এই বিষয়টিতে এই ব্লগ পোস্টটি দেখতে পারেন , আমার খানিকটা আলাদা fers

public interface IDataContextWrapper : IDisposable
{
    Table<T> Table<T>() where T : class;
}

পরবর্তী কাস্টমস্কুলএক্সসেপশন শ্রেণি তৈরি করুন:

public class CustomSqlException : Exception
{
 public CustomSqlException()
 {
 }

 public CustomSqlException(string message, SqlException innerException) : base(message, innerException)
 {
 }
}

এখানে IDataContextWrapper এর একটি নমুনা বাস্তবায়ন:

public class DataContextWrapper<T> : IDataContextWrapper where T : DataContext, new()
{
 private readonly T _db;

 public DataContextWrapper()
 {
        var t = typeof(T);
     _db = (T)Activator.CreateInstance(t);
 }

 public DataContextWrapper(string connectionString)
 {
     var t = typeof(T);
     _db = (T)Activator.CreateInstance(t, connectionString);
 }

 public Table<TableName> Table<TableName>() where TableName : class
 {
        try
        {
            return (Table<TableName>) _db.GetTable(typeof (TableName));
        }
        catch (SqlException exception)
        {
            // Wrap the SqlException with our custom one
            throw new CustomSqlException("Ooops...", exception);
        }
 }

 // IDispoable Members
}

92

আপনি এটি প্রতিবিম্বের সাহায্যে করতে পারেন, মাইক্রোসফ্ট পরিবর্তনগুলি করার সময় আপনাকে এটি বজায় রাখতে হবে, তবে এটি কাজ করে আমি ঠিক এটি পরীক্ষা করেছি:

public class SqlExceptionCreator
{
    private static T Construct<T>(params object[] p)
    {
        var ctors = typeof(T).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance);
        return (T)ctors.First(ctor => ctor.GetParameters().Length == p.Length).Invoke(p);
    }

    internal static SqlException NewSqlException(int number = 1)
    {
        SqlErrorCollection collection = Construct<SqlErrorCollection>();
        SqlError error = Construct<SqlError>(number, (byte)2, (byte)3, "server name", "error message", "proc", 100);

        typeof(SqlErrorCollection)
            .GetMethod("Add", BindingFlags.NonPublic | BindingFlags.Instance)
            .Invoke(collection, new object[] { error });


        return typeof(SqlException)
            .GetMethod("CreateException", BindingFlags.NonPublic | BindingFlags.Static,
                null,
                CallingConventions.ExplicitThis,
                new[] { typeof(SqlErrorCollection), typeof(string) },
                new ParameterModifier[] { })
            .Invoke(null, new object[] { collection, "7.0.0" }) as SqlException;
    }
}      

এটি আপনাকে স্ক্যালএক্সসেপশন সংখ্যা নিয়ন্ত্রণ করতে দেয় যা গুরুত্বপূর্ণ হতে পারে।


4
এই পদ্ধতির কাজ করে, দুটি ওভারলোড হওয়ায় আপনার যেটি ক্রিয়েটএক্সসেপশন পদ্ধতিটি চান সেটি সম্পর্কে আপনাকে আরও সুনির্দিষ্ট হওয়া দরকার। গেটমেথড কলটিতে এই পরিবর্তন করুন: .গেটমথোড ("ক্রিয়েটএক্সেপশন", বাইন্ডিংফ্ল্যাজস.নোনপাবলিক | বাইন্ডিং ফ্ল্যাশস.ট্যাটিক, নাল, কলিংকন্টনস.স্পেসিয়াল, নতুন [] {টাইপফ (স্কেলএররর সংগ্রহ), টাইপফ (স্ট্রিং)}, নতুন প্যারামিটারমডিফায়ার [] এটি কাজ করে
এরিক নর্ডেনহাক

আমার জন্য কাজ কর. উজ্জ্বল।
নিক পাতাসারিস

4
মন্তব্যগুলি থেকে সংশোধন করে একটি সংক্ষেপে পরিণত হয়েছে। gist.github.com/timabell/672719c63364c497377f - এই অন্ধকার অন্ধকার জায়গা থেকে আমাকে একটি উপায় দেওয়ার জন্য সকলকে অনেক ধন্যবাদ।
টিম আবেল

4
বেন জে অ্যান্ডারসনের সংস্করণ আপনাকে ত্রুটি কোড ছাড়াও বার্তা নির্দিষ্ট করতে দেয়। gist.github.com/benjanderson/07e13d9a2068b32c2911
টনি

10
এটি ডটনেট-কোর ২.০ নিয়ে কাজ করার NewSqlExceptionজন্য, পড়ার পদ্ধতিটিতে দ্বিতীয় লাইনটি পরিবর্তন করুন :SqlError error = Construct<SqlError>(number, (byte)2, (byte)3, "server name", "error message", "proc", 100, null);
চক স্পেন্সার

75

আমি এর একটি সমাধান আছে। আমি মেধা না পাগল কিনা তা নিশ্চিত নই।

নিম্নলিখিত কোডটি একটি নতুন স্কেলএক্সসেপশন তৈরি করবে:

public SqlException MakeSqlException() {
    SqlException exception = null;
    try {
        SqlConnection conn = new SqlConnection(@"Data Source=.;Database=GUARANTEED_TO_FAIL;Connection Timeout=1");
        conn.Open();
    } catch(SqlException ex) {
        exception = ex;
    }
    return(exception);
}

যা আপনি এর পরে যেমন ব্যবহার করতে পারেন (উদাহরণটি মাক ব্যবহার করছে)

mockSqlDataStore
    .Setup(x => x.ChangePassword(userId, It.IsAny<string>()))
    .Throws(MakeSqlException());

যাতে আপনি আপনার সংগ্রহস্থল, হ্যান্ডলার এবং নিয়ামকগুলিতে আপনার স্কেলএক্সসেপশন ত্রুটি পরিচালনা করতে পারেন।

এখন আমাকে শুয়ে থাকা দরকার।


10
জমকালো সমাধান! সংযোগের অপেক্ষায় কিছুটা সময় বাঁচানোর জন্য আমি এটিতে একটি পরিবর্তন করেছি:new SqlConnection(@"Data Source=.;Database=GUARANTEED_TO_FAIL;Connection Timeout=1")
জোয়ান্না ডার্কস

4
আপনি আপনার উত্তরে সংবেদন যুক্ত করেছেন তা আমি পছন্দ করি। LOL এই সমাধানের জন্য ধন্যবাদ। এটি কোনও মস্তিষ্কে নেই এবং আমি কেন জানি না কেন প্রাথমিকভাবে আমি এটি সম্পর্কে ভাবিনি। আবার ধন্যবাদ
pqsk

4
দুর্দান্ত সমাধান, কেবলমাত্র আপনার স্থানীয় মেশিনে GUARANTEED_TO_FAIL নামে একটি ডাটাবেস নেই বলে নিশ্চিত করুন;)
অমিত জি

কেআইএসএসের একটি দুর্দান্ত উদাহরণ
লুপ করুন


22

পরিস্থিতির উপর নির্ভর করে, আমি সাধারণত কনস্ট্রাক্টর ইনফোতে প্রার্থনা করার জন্য getUninitializedObject পছন্দ করি । আপনাকে কেবল সচেতন হতে হবে যে এটি কনস্ট্রাক্টরকে কল করে না - এমএসডিএন মন্তব্য থেকে: "যেহেতু বস্তুর নতুন উদাহরণটি শূন্যে আরম্ভ করা হয়েছে এবং কোনও নির্মাণকারী চালিত নয়, বস্তুটি এমন একটি রাষ্ট্রের প্রতিনিধিত্ব করতে পারে না যা বৈধ হিসাবে বিবেচিত হবে "যে বস্তু দ্বারা।" তবে আমি বলতে চাই এটি একটি নির্দিষ্ট নির্মাণকারীর অস্তিত্বের উপর নির্ভর করার চেয়ে কম ভঙ্গুর।

[TestMethod]
[ExpectedException(typeof(System.Data.SqlClient.SqlException))]
public void MyTestMethod()
{
    throw Instantiate<System.Data.SqlClient.SqlException>();
}

public static T Instantiate<T>() where T : class
{
    return System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(T)) as T;
}

4
এটি আমার পক্ষে কাজ করেছে এবং একবার আপনার typeof(SqlException).GetField("_message", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(exception, "my custom sql message");
ফিল কোপার

8
আমি এটিকে ত্রুটিমাখা এবং ত্রুটি কোডের প্রতিবিম্বিত করতে প্রসারিত করেছি। gist.github.com/benjanderson/07e13d9a2068b32c2911
বেন অ্যান্ডারসন

13

ওচ এডিট করুন : আমি বুঝতে পারি না যে স্কেলএক্সসেপশন সিল করা আছে। আমি ডিবিএক্সসেপশনকে উপহাস করছি, এটি একটি বিমূর্ত শ্রেণি।

আপনি একটি নতুন স্কেলএক্সসেপশন তৈরি করতে পারবেন না তবে আপনি একটি ডিবিএক্সসেপশনকে উপহাস করতে পারেন, এটি স্কেলএক্সসেপশন থেকে প্রাপ্ত। এটা চেষ্টা কর:

var ex = new Mock<DbException>();
ex.ExpectGet(e => e.Message, "Exception message");

var conn = new Mock<SqlConnection>();
conn.Expect(c => c.Open()).Throws(ex.Object);

পদ্ধতিটি সংযোগটি খোলার চেষ্টা করলে আপনার ব্যতিক্রম ছুঁড়ে ফেলা হয়।

যদি আপনি Messageউপহাস ব্যতিক্রমের সম্পত্তি ব্যতীত অন্য কিছু পড়ার আশা করেন তবে সেই বৈশিষ্ট্যগুলিতে "পেতে" প্রত্যাশা করবেন না (বা মোকের সংস্করণ অনুসারে সেটআপ করুন)।


"সংখ্যা" এর জন্য আপনার প্রত্যাশা যুক্ত করা উচিত যা আপনাকে কী ধরণের ব্যতিক্রম (ডেডলক, টাইমআউট ইত্যাদি) নির্ধারণ করতে দেয়
স্যাম সাফ্রন

হুঁ আপনার লিঙ্ক ব্যবহার করার সময় কীভাবে? আমি আসলে একটি খোলামেলা করি না (এটি আমার জন্য হয়ে গেছে)।
chobo2

আপনি যদি মাক ব্যবহার করছেন তবে সম্ভবত আপনি কোনও ধরণের ডাটাবেস অপারেশনকে উপহাস করছেন। এটি হওয়ার পরে এটি ছুঁড়ে ফেলার জন্য সেট আপ করুন।
ম্যাট হ্যামিল্টন

তাহলে প্রকৃত অপারেশন (আসল পদ্ধতিটি যা ডিবিকে ডাকবে)?
chobo2

আপনি কি আপনার ডিবি আচরণকে উপহাস করছেন? পছন্দ করুন, আপনার ডেটা কনটেক্সট ক্লাস বা কিছু উপহাস করছেন? ডাটাবেস ক্রিয়াকলাপ একটি ত্রুটি ফিরিয়ে দিলে যে কোনও অপারেশন এই ব্যতিক্রমটিকে ছুঁড়ে ফেলবে।
ম্যাট হ্যামিল্টন

4

এটি সাহায্য করে কিনা তা নিশ্চিত নয় তবে মনে হয় এই ব্যক্তির পক্ষে কাজ করেছেন (বেশ চালাক)।

try
{
    SqlCommand cmd =
        new SqlCommand("raiserror('Manual SQL exception', 16, 1)",DBConn);
    cmd.ExecuteNonQuery();
}
catch (SqlException ex)
{
    string msg = ex.Message; // msg = "Manual SQL exception"
}

পাওয়া গেছে: http://smartypeeps.blogspot.com/2006/06/how-to-throw-sqlexception-in-c.html


আমি এটি চেষ্টা করেছিলাম, তবে আপনার স্কেলএক্সসেপশন নিক্ষেপ করার জন্য আপনার এখনও একটি খোলা স্কেলকনেকশন অবজেক্টের প্রয়োজন।
মুসিজেনেসিস

আমি স্কিল থেকে লিনাক ব্যবহার করি যাতে আমি এই অ্যাডো নেট নেট স্টাফটি না করি। এর সবই পর্দার আড়ালে।
chobo2

2

এই কাজ করা উচিত:

SqlConnection bogusConn = 
    new SqlConnection("Data Source=myServerAddress;Initial
    Catalog=myDataBase;User Id=myUsername;Password=myPassword;");
bogusConn.Open();

ব্যতিক্রম ছুঁড়ে ফেলার আগে এটি কিছুটা সময় নেয়, সুতরাং আমি মনে করি এটি আরও দ্রুত কাজ করবে:

SqlCommand bogusCommand = new SqlCommand();
bogusCommand.ExecuteScalar();

কোড হ্যাকস-আর-ইউএস আপনার কাছে এনেছে।

আপডেট : না, দ্বিতীয় পদ্ধতিটি একটি স্কেলএক্সসেপশন নয়, একটি আর্গুমেন্ট এক্সসেপশন নিক্ষেপ করে।

আপডেট 2 : এটি আরও দ্রুত কাজ করে (স্কেলএক্সসেপশন এক সেকেন্ডেরও কম সময়ের মধ্যে ফেলে দেওয়া হয়):

SqlConnection bogusConn = new SqlConnection("Data Source=localhost;Initial
    Catalog=myDataBase;User Id=myUsername;Password=myPassword;Connection
    Timeout=1");
bogusConn.Open();

এই এসইউ পৃষ্ঠাটি পেরিয়ে আসার আগে এটি আমার নিজের বাস্তবায়ন ছিল অন্য কোনও উপায় সন্ধান করা কারণ সময়সীমা অগ্রহণযোগ্য ছিল। আপনার আপডেট 2 ভাল তবে এটি এখনও এক সেকেন্ড। ইউনিট পরীক্ষা সেটগুলির পক্ষে ভাল নয় কারণ এটি স্কেল করে না।
জন ডেভিস

2

আমি লক্ষ্য করেছি যে আপনার প্রশ্নটি এক বছরের পুরনো, তবে রেকর্ডের জন্য আমি মাইক্রোসফ্ট মোলস ব্যবহার করে সম্প্রতি আবিষ্কার করা একটি সমাধান যুক্ত করতে চাই (আপনি এখানে রেফারেন্সগুলি খুঁজে পেতে পারেন) মাইক্রোসফ্ট মোলস )

একবার আপনি সিস্টেম.ডাটা নেমস্পেসটি moled করার পরে, আপনি কেবল একটি এসকিউএল ব্যতিক্রমটি একটি এসকিউএল সংযোগে উপহাস করতে পারেন O

//Create a delegate for the SqlConnection.Open method of all instances
        //that raises an error
        System.Data.SqlClient.Moles.MSqlConnection.AllInstances.Open =
            (a) =>
            {
                SqlException myException = new System.Data.SqlClient.Moles.MSqlException();
                throw myException;
            };

আমি আশা করি এটি ভবিষ্যতে এই প্রশ্নটিকে হিট করে এমন কাউকে সহায়তা করতে পারে।


4
দেরিতে উত্তর থাকা সত্ত্বেও এটি সম্ভবত সবচেয়ে পরিষ্কার সমাধান, বিশেষত যদি আপনি ইতিমধ্যে অন্য উদ্দেশ্যে মোল ব্যবহার করছেন।
আমন্ডালিশাস

4
ভাল, এটি কাজ করার জন্য আপনাকে অবশ্যই মোলস কাঠামোটি ব্যবহার করতে হবে। ইতিমধ্যে MOQ ব্যবহার করার সময় সম্পূর্ণ আদর্শ নয়। এই সমাধানটি .NET ফ্রেমওয়ার্কের কলকে ডিটোর করে দিচ্ছে। @ Default.kramer এর উত্তর আরও উপযুক্ত। মোলস ভিজ্যুয়াল স্টুডিও 2012 আলটিমেটে "ফেকস" হিসাবে প্রকাশিত হয়েছিল এবং পরে ভিএস 2012 প্রিমিয়ামে আপডেট 2 এর মাধ্যমে প্রকাশিত হয়েছিল, আমি জালিয়াতি কাঠামোটি ব্যবহার করার জন্যই আছি, তবে আগত লোকের স্বার্থে একটি সময়ে একটি উপহাসের কাঠামোর সাথে লেগে থাকি তোমার পরে. ;)
মাইক ক্রিশ্চিয়ান

2

আমি এই পদ্ধতিটি ব্যবহার করার পরামর্শ দিচ্ছি।

    /// <summary>
    /// Method to simulate a throw SqlException
    /// </summary>
    /// <param name="number">Exception number</param>
    /// <param name="message">Exception message</param>
    /// <returns></returns>
    public static SqlException CreateSqlException(int number, string message)
    {
        var collectionConstructor = typeof(SqlErrorCollection)
            .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, //visibility
                null, //binder
                new Type[0],
                null);
        var addMethod = typeof(SqlErrorCollection).GetMethod("Add", BindingFlags.NonPublic | BindingFlags.Instance);
        var errorCollection = (SqlErrorCollection)collectionConstructor.Invoke(null);
        var errorConstructor = typeof(SqlError).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null,
            new[]
            {
                typeof (int), typeof (byte), typeof (byte), typeof (string), typeof(string), typeof (string),
                typeof (int), typeof (uint)
            }, null);
        var error =
            errorConstructor.Invoke(new object[] { number, (byte)0, (byte)0, "server", "errMsg", "proccedure", 100, (uint)0 });
        addMethod.Invoke(errorCollection, new[] { error });
        var constructor = typeof(SqlException)
            .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, //visibility
                null, //binder
                new[] { typeof(string), typeof(SqlErrorCollection), typeof(Exception), typeof(Guid) },
                null); //param modifiers
        return (SqlException)constructor.Invoke(new object[] { message, errorCollection, new DataException(), Guid.NewGuid() });
    }

পর্যালোচনা সারি থেকে : আমি আপনাকে অনুরোধ করতে দয়া করে আপনার উত্তর কাছাকাছি আরও কিছু প্রসঙ্গ যুক্ত করুন। কোড-কেবল উত্তরগুলি বোঝা মুশকিল। আপনি যদি আপনার পোস্টে আরও তথ্য যুক্ত করতে পারেন তবে এটি প্রশ্নকারী এবং ভবিষ্যতের পাঠকদের উভয়কেই সহায়তা করবে।
আরবিটি

আপনি পোস্টটি নিজে সম্পাদনা করে এই তথ্য যুক্ত করতে চাইতে পারেন। উত্তর সম্পর্কিত প্রাসঙ্গিক তথ্য বজায় রাখতে পোস্ট করা মন্তব্যগুলির চেয়ে ভাল জায়গা।
আরবিটি

এটি আর কাজ SqlExceptionকরে না কারণ কোনও কনস্ট্রাক্টর নেই এবং errorConstructorএটি বাতিল হবে।
ইমাদ

@ ইমাদ, সমস্যাটি কাটিয়ে উঠতে আপনি কী ব্যবহার করেছেন?
সাসুক উচিহ

2

থিজ সলিউশনগুলি ফুলে যায় বলে মনে হয়।

কর্টরটি অভ্যন্তরীণ, হ্যাঁ।

(প্রতিবিম্ব ব্যবহার না করে, খাঁটিভাবে এই ব্যতিক্রমটি তৈরি করার সবচেয়ে সহজ উপায় ....

   instance.Setup(x => x.MyMethod())
            .Callback(() => new SqlConnection("Server=pleasethrow;Database=anexception;Connection Timeout=1").Open());

অনুভূতিগুলির একটি অন্য পদ্ধতি রয়েছে যা ছোঁড়াতে 1 সেকেন্ডের সময়সীমা প্রয়োজন হয় না।


হাহ ... এত সহজ আমি জানি না কেন আমি এটিকে কেন ভাবি নি ... ঝামেলা ছাড়াই নিখুঁত এবং আমি এটি যে কোনও জায়গায় করতে পারি।
hal9000

একটি বার্তা এবং একটি ত্রুটি কোড স্থাপন সম্পর্কে কি? দেখে মনে হচ্ছে আপনার সমাধান এটির অনুমতি দেয় না।
সাসুক উচিহ

@ সাসুক উচিহ নিশ্চিত, এটি হয় না। অন্যান্য সমাধান না। তবে যদি আপনাকে কেবল এই ধরণের ব্যতিক্রম ছোঁড়াতে হয়, প্রতিবিম্ব এড়াতে চান এবং খুব বেশি কোড না লিখতে চান তবে আপনি এই সমাধানটি ব্যবহার করতে পারেন।
বিলি জ্যাক ও'কনোর

1

(দুর্দান্ত 6 মাস দেরি হয়ে গেছে, আশা করি এটি কোনও উপহাস থেকে স্ক্যালসিএক্সপশন কীভাবে নিক্ষেপ করতে হবে তা সন্ধান করতে আমি এখানে অবতরণ করেছি নেক্রোপোস্টিং হিসাবে বিবেচিত হবে না))

যদি আপনাকে কেবল ব্যতিক্রমটি পরিচালনা করে এমন কোডটি পরীক্ষা করতে হয় তবে একটি অতি সাধারণ কাজ হতে পারে:

public void MyDataMethod(){
    try
    {
        myDataContext.SubmitChanges();
    }
    catch(Exception ex)
    {
        if(ex is SqlCeException || ex is TestThrowableSqlCeException)
        {
            // handle ex
        }
        else
        {
            throw;
        }
    }
}



public class TestThrowableSqlCeException{
   public TestThrowableSqlCeException(string message){}
   // mimic whatever properties you needed from the SqlException:
}

var repo = new Rhino.Mocks.MockReposity();
mockDataContext = repo.StrictMock<IDecoupleDataContext>();
Expect.Call(mockDataContext.SubmitChanges).Throw(new TestThrowableSqlCeException());

1

অন্যান্য সমস্ত উত্তরের ভিত্তিতে আমি নিম্নলিখিত সমাধানটি তৈরি করেছি:

    [Test]
    public void Methodundertest_ExceptionFromDatabase_Logs()
    {
        _mock
            .Setup(x => x.MockedMethod(It.IsAny<int>(), It.IsAny<string>()))
            .Callback(ThrowSqlException);

        _service.Process(_batchSize, string.Empty, string.Empty);

        _loggermock.Verify(x => x.Error(It.IsAny<string>(), It.IsAny<SqlException>()));
    }

    private static void ThrowSqlException() 
    {
        var bogusConn =
            new SqlConnection(
                "Data Source=localhost;Initial Catalog = myDataBase;User Id = myUsername;Password = myPassword;Connection Timeout = 1");
        bogusConn.Open();
    }

1

এটি সত্যিই পুরানো এবং এখানে কিছু ভাল উত্তর রয়েছে। আমি মোক ব্যবহার করছি, এবং আমি অ্যাবস্ট্রাক্ট ক্লাসগুলি উপহাস করতে পারি না এবং সত্যই প্রতিচ্ছবি ব্যবহার করতে চাই না, তাই আমি ডিবিএক্সেপশন থেকে প্রাপ্ত আমার নিজস্ব ব্যতিক্রম তৈরি করেছি। সুতরাং:

public class MockDbException : DbException {
  public MockDbException(string message) : base (message) {}
}   

স্পষ্টতই, আপনার যদি অভ্যন্তরীণ ধারণা বা যা কিছু যোগ করার দরকার হয় তবে আরও প্রপস, কনস্ট্রাক্টর ইত্যাদি যুক্ত করুন

তারপরে, আমার পরীক্ষায়:

MyMockDatabase.Setup(q => q.Method()).Throws(new MockDbException(myMessage));

হ্যালো, মোখ ব্যবহার করে এমন যে কোনও ব্যক্তিকে এটি সহায়তা করবে। এখানে পোস্ট করা প্রত্যেকের জন্য ধন্যবাদ যা আমাকে আমার উত্তরের দিকে নিয়ে গেছে।


যখন আপনার এসকিএলএক্সসেপশন সম্পর্কিত সুনির্দিষ্ট কিছু লাগবে না, তখন এই পদ্ধতিটি খুব ভালভাবে কাজ করে।
র‌্যাল্ফ উইলগাস

0

আপনি পরীক্ষায় SqlException অবজেক্ট তৈরি করতে প্রতিবিম্ব ব্যবহার করতে পারেন:

        ConstructorInfo errorsCi = typeof(SqlErrorCollection).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[]{}, null);
        var errors = errorsCi.Invoke(null);

        ConstructorInfo ci = typeof(SqlException).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(SqlErrorCollection) }, null);
        var sqlException = (SqlException)ci.Invoke(new object[] { "Exception message", errors });

এটি কাজ করবে না; SqlException এর কোনও কনস্ট্রাক্টর নেই। @ ডিফল্ট.ক্র্যামারের উত্তর সঠিকভাবে কাজ করে।
মাইক খ্রিস্টান

4
@ মাইকচ্রিস্টিয়ান আপনি যদি এমন কোন কন্ডাক্টর ব্যবহার করেন তবে এটি কাজ করবে যেমনprivate SqlException(string message, SqlErrorCollection errorCollection, Exception innerException, Guid conId)
শন উইল্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.