[SalesForce] REQUIRED_FIELD_MISSING error in OpportunityContactRole trigger test

i have written before insert trigger on quote,when inserting a quote i want to populate contact detail like name,email,phone,fax from opportunity the contact which is acting as a contactroles related list in opportunity.this is working fine i write test class but i did not get coverage.sometimes method is passing and getting 57% coverage.it is not covering from line no 21 to 27 please help me out

Class

/****
This class is responsible for Auto populate Contact fileds like contactname,
email,phone,fax from opportunity into Quote when opportunity has Contactroles
relatedlist
***/

public class AutoPopulateContactFieldsInQuoteHelper {

    public void PopulateContactFieldsInQuote(list<Quote> quotelist1){

        List<Quote> quoteList = new List<Quote>();
        Map<String, Quote> QuotetoOpportunityIDMap = new Map<String, Quote>();
        for( Quote Qid : quotelist1 )
        {
            QuotetoOpportunityIDMap.put( Qid.OpportunityID, Qid ); 
        } 

        List<OpportunityContactRole> Contactlist = [select OpportunityID, IsPrimary,ContactID,contact.email,contact.phone,contact.fax from OpportunityContactRole where OpportunityID in :QuotetoOpportunityIDMap.keySet() and IsPrimary = true];

        for (OpportunityContactRole oppConrole : Contactlist) {                            

            Quote quoteToUpdate = QuotetoOpportunityIDMap.get(oppConrole.OpportunityID);

            quoteToUpdate.ContactId = oppConrole.ContactId;       
            quoteToUpdate.phone = oppConrole.Contact.phone;
            quoteToUpdate.fax = oppConrole.Contact.fax;
            quoteToUpdate.email = oppConrole.Contact.email;
            quoteList.add(quoteToUpdate);       
        }
    }
}

test class

@isTest
public class AutoPopulateContactFieldsInQuoteTest{
    static testmethod void PopulateContactFieldsInQuoteTest(){
        account a=new account();
        a.name='tes';
        insert a;

        contact c=new contact();
        c.lastname='ctes';
        c.accountid=a.id;
        insert c;

        opportunity o = new opportunity();
        o.name = 'Testoppty';
        o.StageName = 'lead';
        o.CloseDate = date.today();
        o.accountid = a.Id;
        o.Billing_Type__c='Aggregate';
        insert o;

        quote q=new quote();
        q.name='tesq';
        q.contactid=c.id;
        q.email='g@gg.com';
        insert q;

    }
}

Best Answer

For Quote Object ,the reference to Opportunity is mandatory.

The below code will link quote to opportunity

quote q=new quote();
q.name='tesq';
q.contactid=c.id;
q.email='g@gg.com';
q.opportunityId = o.Id;//Link Quote and opportunity record
insert q;

Apart from this ,You will also need to create OpportunityContactRole records by referencing opportunity and contact